Enum TypeScript: numerici, string, const e le alternative | We.Inc
Genera enum numerici, string e const a partire dai nomi dei tuoi membri, guarda il JavaScript esatto che ciascuno produce e confrontali con gli oggetti as const e le union di literal.
Un enum dà un unico tipo a un insieme di costanti con nome. Gli enum numerici contano a partire da 0 e mappano anche i numeri ai nomi; gli enum string richiedono un literal per ogni membro e non hanno reverse mapping; i const enum vengono inseriti inline e spariscono. A differenza della maggior parte di TypeScript, gli enum normali producono vero JavaScript, per questo molti team preferiscono gli oggetti as const.
Cinque modi per modellare un insieme fisso di valori
Stile
Produce JavaScript?
Reverse mapping
Accetta un literal diretto?
Enum numerico
Sì, un oggetto
Sì, da numero a nome
Numeri che corrispondono a un membro
Enum string
Sì, un oggetto
No
No, bisogna usare Enum.Member
const enum
No, valori inline
No
Come il suo tipo di enum
Oggetto as const
Sì, un oggetto semplice
No (scrivine uno se serve)
Sì
Union di literal
No, rimosso
No
Sì
Scrivi i nomi dei membri nel generatore e passa da uno stile all'altro. Scrive la dichiarazione TypeScript e il JavaScript che il compilatore produrrebbe, così puoi vedere il costo di ogni scelta prima che finisca nel tuo bundle.
Inserisci i nomi dei membri separati da virgole, per esempio Draft, Review, Live.
Per gli enum numerici, imposta il numero iniziale; i membri successivi contano a partire da esso.
Scegli uno stile per vederne la dichiarazione, il JavaScript prodotto e come si usa.
Copia la versione adatta al tuo progetto.
Scegli enum string o oggetti as const per i valori che escono dal tuo programma, come campi di API o colonne del database. Una riga di log che dice live è più facile da leggere di 2.
Non riordinare né inserire mai membri a metà di un enum numerico che viene salvato da qualche parte. Ogni numero successivo si sposta e i vecchi dati salvati ora significano altro.
Evita const enum nelle librerie pubblicate. I consumatori compilati con isolatedModules o con un type stripper non possono inserire inline valori da un altro file.
Attiva erasableSyntaxOnly se esegui file .ts con il type stripping di Node; segnala gli enum prima che falliscano a runtime.
Domande frequenti
Cos'è un reverse mapping?
Per gli enum numerici tsc salva entrambe le direzioni nell'oggetto, quindi Direction.Up è 0 e Direction[0] è la stringa Up. I membri string non hanno una voce inversa, perché il valore potrebbe coincidere con il nome di un altro membro.
Perché non posso passare una semplice stringa a una funzione che accetta un enum string?
I membri degli enum string sono tipi distinti. Il compilatore segnala che il literal non è assegnabile all'enum, quindi chi chiama deve scrivere Status.Draft. Se vuoi che chi chiama passi il literal, usa invece una union di string literal.
Come itero sui valori di un enum?
Per un enum string, Object.values(MyEnum) restituisce i valori. Per un enum numerico l'oggetto contiene anche le chiavi inverse, quindi filtra: Object.values(MyEnum).filter((v) => typeof v === 'number').
Gli enum sono deprecati?
No. Restano parte di TypeScript. La più recente opzione erasableSyntaxOnly, aggiunta in TypeScript 5.8, permette semplicemente ai progetti che si basano sul type stripping di vietarli, perché un enum non si può rimuovere cancellando le annotazioni.
Node.js esegue direttamente i file con enum?
Non con il type stripping predefinito. La documentazione di Node elenca le dichiarazioni enum tra le funzionalità che richiedono generazione di codice e non sono supportate in quella modalità, quindi compilale con tsc o un altro transformer, oppure passa a un oggetto as const.
Enum numerici: compatti ma fragili
Senza inizializzatori, i membri sono numerati 0, 1, 2 in ordine. Dai un valore al primo, come Low = 1, e gli altri continuano da lì. L'oggetto prodotto contiene sia la mappa da nome a numero sia quella da numero a nome.
Questa compattezza è anche il rischio. I numeri non significano nulla fuori dal tuo codice, e aggiungere un membro a metà rinumera in silenzio tutto ciò che viene dopo.
Enum string: leggibili e rigorosi
Ogni membro richiede uno string literal, il che rende i valori autoesplicativi nei log, negli URL e nel JSON. Il rigore vale in entrambe le direzioni: un valore letto da un'API è una stringa, non l'enum, quindi serve comunque un controllo prima di trattarlo come tale.
Lo schema as const
Un object literal marcato as const mantiene i suoi valori stringa esatti come tipi. Abbinalo a type Role = (typeof Role)[keyof typeof Role] e ottieni un oggetto a runtime da iterare più un tipo union che accetta sia Role.Admin sia il literal admin.
È semplice JavaScript con annotazioni, quindi ogni type stripper lo gestisce, e non viene generato nulla oltre all'oggetto che hai scritto.
I tre tipi di enum e cosa producono
Enum numerico con un valore iniziale
Mid e High continuano a contare da Low. L'oggetto prodotto mappa in entrambe le direzioni.
Enum string
Ogni membro viene assegnato una volta, senza voce inversa.
const enum
La dichiarazione sparisce e ogni utilizzo diventa il suo valore.
Alternative cancellabili
Oggetto as const più una union derivata
Funziona con i type stripper, si itera con Object.values e accetta la stringa diretta.
Union semplice quando non serve una lista a runtime
Rimossa del tutto; il compilatore rifiuta comunque qualsiasi altra stringa.
Vietare gli enum in un progetto con type stripping
Con questa opzione, una dichiarazione enum è un errore di compilazione.
Enum numerico
Enum string
const enum
Oggetto as const
Tipo union
Generatore di enum
Nome del tipo
Membri (separati da virgole)
Primo numero
Stile dell'enum
TypeScript
JavaScript prodotto
Copia TypeScript
Copia JavaScript
Usa nomi che iniziano con una lettera, $ o _, e contengono solo lettere, cifre, $ o _, senza usare due volte lo stesso nome.