Vad är bästa praxis för att implementera ett alternativ till TypeScript `enum`?


Jag lärde mig från en kurs att den inbyggda enum från TypeScript bör undvikas. Den sa åt mig att använda följande istället:

const MyEnum = {
  name: 'name',
  email: 'email'
} as const;
type MyEnum = keyof typeof MyEnum;

Jag förstår fördelarna med detta:

  1. Jag kan alltid ha MyEnum.name som ett argument var som helst som accepterar en MyEnum.
  2. Jag kan alltid använda en strängliteral som 'name' var som helst som accepterar en MyEnum. Detta undviker behovet av att importera MyEnum när strängliteral används.
  3. Object.keys(MyEnum) kommer inte att inkludera både nyckel- och värdetyp när MyEnum består av nummer istället för strängliteraler.

Jag vill behålla dessa fördelar. Men i den nuvarande implementeringen som tillhandahålls av kursen måste jag fortfarande skriva en strängliteral för varje nyckel. Är det möjligt att undvika detta? Till exempel, jag tänker på om jag kan skapa en sådan enum med hjälp av en array ['name', 'email']?

Svar #1

Det enklaste sättet är helt enkelt att använda unioner av strängliteraler:

type MyEnum = "name" | "email";

Finns det någon funktion av enum som du saknar i detta?

Redigera:

Om du behöver kunna iterera genom de möjliga värdena för enum, kan du faktiskt skapa det från en array:

const myValues = ["name", "email"];
type MyEnum = typeof myValues[number];

Jag förstår egentligen inte varför det är viktigt att kunna referera till värdena med MyEnum.name-syntaxen, när "name" är kortare, inte kräver några imports och inte har några nackdelar som jag kan komma på.

Om du verkligen vill, kan du förmodligen fortfarande göra det med något som detta (otestat, du kan behöva ge det ett annat namn):

const MyEnum = Object.fromEntries(myValues.map(v => [v, v])) as {
  [K in MyEnum]: K;
};