Hur kan jag iterera över en egen litteraltyp i TypeScript?


Jag har definierat en anpassad literaltyp i TypeScript:

export type Market = 'au'|'br'|'de';

Nu vill jag iterera över varje möjlig Market utan att först behöva skapa en array av Market[] eftersom det känns överflödigt och jag kan glömma att lägga till ett alternativ:

const markets: Market[] = ['au', 'br', 'de'];
markets.forEach((market: Market) => {
    console.log(market);
});

Finns det ett sätt att uppnå det med TypeScript?

Svar #1

För er som besöker denna fråga och använder TypeScript >= 3.4, tror jag att bästa praxis nu är att skapa en konstant array av strängar och sedan använda typen av operatorn.

Exempel :

export const markets = ['au', 'br', 'de'] as const;
export type Market = typeof markets[number];

markets.forEach((market: Market) => {
    console.log(market);
});

Svar #2

Nej, du kan inte göra det, eftersom ren typinformation som den inte existerar vid körning.

Det är hypotetiskt möjligt att göra på det andra sättet (definiera en normal lista med strängar, och sedan härleda typen 'au'|'br'|'de' från den), men jag tror inte att TypeScript-kompilatorn (varken 2.0 eller 2.1) för närvarande kommer att härleda det åt dig - såvitt jag vet kommer typen av markets normalt alltid att vara string[].

Det rätta svaret på detta är att använda enums. De definierar en typ med varje av deras värden, och det är möjligt att få en lista över alla deras strängvärden: Hur programmeringsmässigt lista ett enum-typ i Typescript 0.9.5?.

Den enda nackdelen med enum är att deras körningstidrepresentation är annorlunda (under huven är de faktiskt siffror, inte strängar). Din kod kan fortfarande behandla dem som fina läsbara värden, det är bara att du måste översätta dem till strängar om du någonsin behöver dem som strängnamn vid körning. Det är dock enkelt: givet enum MarketEnum och ett värde myEnumValue, MarketEnum[myEnumValue] är värdets namn som en sträng).

Relaterade artiklar