typescript - Begrens objekts egenskaper til keyof-grensesnitt
denne koden vil ikke kompilere:
interface IFoo {
a: number;
}
type TFoo = keyof IFoo;
type OFoo = { [key: TFoo]: any };
let obj: OFoo = { a: 1 };
Det jeg prøver å oppnå er at obj kun skal kunne tildeles med objekter med gyldige egenskaper, som om jeg skrev:
let obj: IFoo = { a: 1};
men jeg må gjøre det ved hjelp av keyof.
Takk for alle forslag.
Svar #1
Selv om du ikke kan bruke annet enn string eller number som nøkkeltype i en indeks-signatur (og definisjonen din av OFoo vil gi deg en feil i den forbindelse), kan du begrense nøkler til en subtype av string ved å bruke mapped types. Siden TFoo, også kjent som keyof Foo, er en subtype av string, kan du bruke en mapped type slik:
type OFoo = { [K in TFoo]: any };
Merk at syntaksen for kartlagte typer skiller seg fra syntaksen for vanlige indeksignaturer. TFoo ovenfor tilsvarer typen for tillatte nøkler, som i ditt tilfelle bare er "a", men det kunne også være en union av streng-litteraler som "a"|"b"|"c", eller til og med string. Og K ovenfor er en parameter som tilsvarer typen til nøkkelen for hver egenskap. (Du bryr deg egentlig ikke om K siden typen for hver egenskaps verdi er any og ikke har noe å gjøre med K, men du kunne ha brukt K for å plukke ut bestemte egenskaper hvis du ønsket det.) Uansett, la oss bruke det:
let obj: OFoo = { a: 1 }; // okay
let obj = { }; // error, property 'a' is missing
let obj = { c: 1 }; // error, excess property 'c'
Forresten, jeg vil sannsynligvis bruke den innebygde standardbibliotektypen Record<K,T> som er definert slik:
type Record<K extends string, T> = {
[P in K]: T
}
Eller, du kan tenke: "en Record<K, T> er et objekt hvor hver nøkkel er i K og hver verdi er en T". Og for deg, er K TFoo, og T er any:
type OFoo = Record<TFoo, any>; // same thing
Håper det hjelper; lykke til!
