Karta enum-värden till individuella typer i TypeScript
Jag har en bit TypeScript-kod som ser ut så här:
enum EventType {
EVENT_A = 'eventA',
EVENT_B = 'eventB',
... // more event types
}
interface Event {
type: EventType;
}
interface EventA extends Event {
type: EventType.EVENT_A;
data: PayloadForEventA;
}
interface EventB extends Event {
type: EventType.EVENT_B;
data: PayloadForEventB;
id: number;
}
... // More Event interfaces
Är det möjligt att på något sätt koppla värdena i EventType till motsvarande gränssnitt? Om det inte går att göra automatiskt, är det möjligt att specificera typerna som kopplas till enum-värdena manuellt?
Jag vet att det är möjligt att mappa värden till typer som visas i den här frågan. Och genom att använda metoden som visas nedan, skulle det kunna skapa uppslags-tabellen jag behövde:
type EventTypeLut = {
'eventA': EventA,
'eventB': EventB,
// ...
};
Men denna metod hårdkodar värdet av enum i LUT:en. Enum-värdet kan ändras i framtiden (vilket jag inte har mycket kontroll över) och att hårdkoda enum-värdet gör det svårare att underhålla.
När jag försöker använda EventType.EVENT_A som nyckelnamn, klagar TypeScript med "egenskap eller signatur förväntad". Att använda en template-sträng verkar inte heller fungera. (Det verkar som att nyckelnamnet inte kan beräknas, även om det är ett konstant uttryck som 1+2.)
Anledningen till att jag försöker göra detta är att jag vill skapa en typad EventEmitter med enum-värdet av EventType som namn och respektive typat objekt för callback-funktionen. Om det finns ett bättre sätt att uppnå detta, vänligen ge också en ledtråd. Tack på förhand.
Svar #1
Förutom @chharvey:s svar, kan du också säkerställa att alla EventType-nycklar inkluderas i EventTypeLut genom att göra något som:
type EventTypeLut = {
[T in EventType]: {
[EventType.EVENT_A]: EventA,
[EventType.EVENT_B]: EventB,
}[T]
};
The [T in Event] kommer få TypeScript att klaga om inte alla enum-medlemmar anges.
Svar #2
Objektliteraler (och därmed gränssnitt och objekttyper) kan ha beräknade nycklar. Till exempel:
const obj = {
[2 + 2]: 'four'
};
obj[2 + 2] === 'four'; // true
obj[1 + 3] === 'four'; // true
obj[4] === 'four'; // true
obj['4'] === 'four'; // true
Beräknade nycklar är uttryck inneslutna i parenteser som kan användas som nycklar i ett objektliteralt, interface eller objekttyp. Försök använda beräknade nycklar för din EventTypeLut objekttyp:
type EventTypeLut = {
[EventType.EVENT_A]: EventA,
[EventType.EVENT_B]: EventB,
// ...
};
