union - Hur man skapar en strängliteraltyp för nycklarna i en indexerbar typ i TypeScript?
Jag har en indexerbar typ i TypeScript med nycklar som antingen kan vara strängar eller nummer, så här:
export type MyRecords = { [name: string]: string | number };
const myRecords: MyRecords = {
foo: 'a',
bar: 1,
};
Jag vill skapa en strängliteraltyp som endast inkluderar strängnycklarna i denna typ, så att jag kan använda den för att säkerställa typ-säkerhet i min kod. Till exempel:
type KeysOfMyRecords = /* ??? */;
const key: KeysOfMyRecords = 'foo'; // should be OK
const invalidKey: KeysOfMyRecords = 'invalid'; // should cause a error
Jag har försökt följande utan framgång:
type KeysOfMyRecords = keyof typeof myRecords;
Skulle detta vara möjligt?
Svar #1
Jag tror att du kan använda en generisk för att uppnå detta:
export type MyRecords<T extends string | number | symbol> = Record<T, string | number>
const myRecords : MyRecords<'foo' | 'bar'>= {
foo: 'a',
bar: 1,
};
type KeysOfMyRecords = keyof typeof myRecords;
const key: KeysOfMyRecords = 'foo'; // should be OK
const invalidKey: KeysOfMyRecords = 'invalid'; // should cause a error
Nackdelen, som du såg ovan, är att du måste nämna nycklarna när du definierar ditt objekt.
Länk
Problemet med din förväntan är att vi vill att myRecords ska vara av en viss typ MyRecords. Nu har vi explicit definierat MyRecords-typen till att ha sträng som nyckel, och det betyder vilken som helst sträng. Vi skulle också kunna ha använt const-påstående direkt i din kod, men det skulle inte garantera typesäkerhet med MyRecords-typen.
