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!

Relaterte artikler