typescript - Bevara nyckeltyp vid användning av Object.entries()
Här är ett exempel på mitt problem (demo i ts-lekplatsen)
type Tkey = 'foo' | 'bar' | 'defaultKey'
const typedObject: Record<Tkey, Boolean> = {
'foo': true,
'bar': false,
'defaultKey': true
}
// type does not persist string narrowing
const entries = Object.entries(typedObject) // [string, Boolean][]
Så key i [key, values] är av typen string och inte av typen Tkey.
Som en lösning kan du manuellt tvinga efteråt, men det skulle vara trevligt att definiera typen under operationen.
const typedEntries = entries as [Tkey, Boolean][]
Svar #1
Du kan utöka standard TypeScript-biblioteket genom att lägga till din egen objektdefinition som tar in två generiska typparameterar.
Lägg till följande i en globals.d.ts-fil i din projektrot:
interface ObjectConstructor {
entries<TKey extends PropertyKey, TVal>(o: Record<TKey,TVal>): [TKey, TVal][];
keys<TKey extends PropertyKey>(obj: Record<TKey,any>): TKey[];
}
Och sedan använd det så här:
const entries = Object.entries<ObjKeys, Boolean>(myObj) // [ObjKeys, Boolean][]
const keys = Object.keys<ObjKeys>(myObj) // ObjKeys[]
Demo i TS Playground
Svar #2
TypeScripts inbyggda definitionsfiler innehåller detta för Object.entries:
entries<T>(o: { [s: string]: T } | ArrayLike<T>): [string, T][];
entries(o: {}): [string, any][];
Din enda chans att få det beteende du vill ha är att åsidosätta denna definition med något liknande detta:
interface YourOwnObject {
entries<T>(o: { [K in keyof T]: T[K] }): [keyof T, T[keyof T]][];
}
(<YourOwnObject>Object).entries(typedObject).forEach(([key, values]) => {
// ...
})
