TypeScript-Enum: numerisch, String, const und die Alternativen | We.Inc
Erzeuge numerische, String- und const-Enums aus deinen eigenen Member-Namen, sieh das genaue JavaScript, das jedes ausgibt, und vergleiche sie mit as-const-Objekten und Literal-Unions.
Ein Enum gibt einer Menge benannter Konstanten einen gemeinsamen Typ. Numerische Enums zählen ab 0 hoch und bilden Zahlen auch zurück auf Namen ab. String-Enums brauchen ein Literal pro Member und haben kein Reverse Mapping. const-Enums werden inline eingesetzt und verschwinden. Anders als das meiste in TypeScript erzeugen normale Enums echtes JavaScript, deshalb bevorzugen viele Teams as-const-Objekte.
Fünf Wege, eine feste Menge von Werten abzubilden
Stil
Erzeugt JavaScript?
Reverse Mapping
Akzeptiert ein rohes Literal?
Numerisches Enum
Ja, ein Objekt
Ja, Zahl zu Name
Zahlen, die zu einem Member passen
String-Enum
Ja, ein Objekt
Nein
Nein, Enum.Member ist Pflicht
const enum
Nein, Werte inline eingesetzt
Nein
Wie seine Enum-Art
as-const-Objekt
Ja, ein einfaches Objekt
Nein (bei Bedarf selbst schreiben)
Ja
Union aus Literalen
Nein, entfernt
Nein
Ja
Gib Member-Namen in den Generator ein und wechsle zwischen den Stilen. Er schreibt die TypeScript-Deklaration und das JavaScript, das der Compiler ausgeben würde, damit du die Kosten jeder Wahl siehst, bevor sie in deinem Bundle landet.
Gib Member-Namen durch Kommas getrennt ein, zum Beispiel Draft, Review, Live.
Lege bei numerischen Enums die Startzahl fest, spätere Member zählen von dort hoch.
Wähle einen Stil, um seine Deklaration, das erzeugte JavaScript und die Verwendung zu sehen.
Kopiere die Version, die zu deinem Projekt passt.
Wähle String-Enums oder as-const-Objekte für Werte, die dein Programm verlassen, etwa API-Felder oder Datenbankspalten. Eine Logzeile mit live ist leichter zu lesen als 2.
Ordne in einem numerischen Enum, das irgendwo gespeichert wird, nie Member um und füge nie welche in der Mitte ein. Jede spätere Zahl verschiebt sich, und alte gespeicherte Daten bedeuten plötzlich etwas anderes.
Vermeide const enum in veröffentlichten Bibliotheken. Nutzer, die mit isolatedModules oder einem Type Stripper kompilieren, können Werte aus einer anderen Datei nicht inline einsetzen.
Aktiviere erasableSyntaxOnly, wenn du .ts-Dateien mit dem Type Stripping von Node ausführst. Es markiert Enums, bevor sie zur Laufzeit scheitern.
Häufige Fragen
Was ist ein Reverse Mapping?
Bei numerischen Enums speichert tsc beide Richtungen im Objekt, Direction.Up ist also 0 und Direction[0] der String Up. String-Member bekommen keinen umgekehrten Eintrag, weil der Wert mit dem Namen eines anderen Members kollidieren könnte.
Warum kann ich keinen einfachen String an eine Funktion übergeben, die ein String-Enum erwartet?
String-Enum-Member sind eigene Typen. Der Compiler meldet, dass das Literal dem Enum nicht zuweisbar ist, Aufrufer müssen also Status.Draft schreiben. Wenn Aufrufer das Literal übergeben sollen, nutze stattdessen eine Union aus String-Literalen.
Wie iteriere ich über Enum-Werte?
Bei einem String-Enum liefert Object.values(MyEnum) die Werte. Bei einem numerischen Enum enthält das Objekt auch die umgekehrten Schlüssel, filtere also: Object.values(MyEnum).filter((v) => typeof v === 'number').
Sind Enums veraltet?
Nein. Sie bleiben Teil von TypeScript. Die neuere Option erasableSyntaxOnly, eingeführt in TypeScript 5.8, erlaubt Projekten, die auf Type Stripping setzen, sie einfach zu verbieten, weil sich ein Enum nicht durch Löschen von Annotationen entfernen lässt.
Führt Node.js Dateien mit Enums direkt aus?
Nicht mit dem standardmäßigen Type Stripping. Die Node-Dokumentation zählt Enum-Deklarationen zu den Funktionen, die Codegenerierung brauchen und in diesem Modus nicht unterstützt werden. Kompiliere sie also mit tsc oder einem anderen Transformer oder wechsle zu einem as-const-Objekt.
Numerische Enums: kompakt, aber fragil
Ohne Initialisierer werden Member der Reihe nach mit 0, 1, 2 nummeriert. Gib dem ersten einen Wert, etwa Low = 1, und der Rest zählt von dort weiter. Das erzeugte Objekt enthält sowohl Name zu Zahl als auch Zahl zu Name.
Genau diese Kompaktheit ist auch das Risiko. Die Zahlen bedeuten außerhalb deines Codes nichts, und ein in der Mitte eingefügter Member nummeriert stillschweigend alles danach neu.
String-Enums: lesbar und streng
Jeder Member braucht ein String-Literal, wodurch Werte in Logs, URLs und JSON selbsterklärend sind. Die Strenge hat zwei Seiten: Ein von einer API gelesener Wert ist ein String, nicht das Enum, du brauchst also trotzdem eine Prüfung, bevor du ihn als solches behandelst.
Das as-const-Muster
Ein mit as const markiertes Objektliteral behält seine exakten String-Werte als Typen. Kombiniere es mit type Role = (typeof Role)[keyof typeof Role], und du bekommst ein Laufzeitobjekt zum Iterieren plus einen Union-Typ, der sowohl Role.Admin als auch das Literal admin akzeptiert.
Das ist einfaches JavaScript mit Annotationen, jeder Type Stripper kommt also damit klar, und außer dem Objekt, das du geschrieben hast, wird nichts zusätzlich erzeugt.
Die drei Enum-Arten und was sie erzeugen
Numerisches Enum mit Startwert
Mid und High zählen von Low aus weiter. Das erzeugte Objekt bildet in beide Richtungen ab.
String-Enum
Jeder Member wird einmal zugewiesen, ohne umgekehrten Eintrag.
const enum
Die Deklaration verschwindet, und jede Verwendung wird zu ihrem Wert.
Entfernbare Alternativen
as-const-Objekt plus abgeleitete Union
Funktioniert mit Type Strippern, lässt sich mit Object.values durchlaufen und akzeptiert den rohen String.
Einfache Union, wenn keine Liste zur Laufzeit nötig ist
Wird vollständig entfernt, der Compiler lehnt trotzdem jeden anderen String ab.
Enums in einem Projekt mit Type Stripping verbieten
Mit dieser Option ist eine Enum-Deklaration ein Kompilierfehler.
Numerisches Enum
String-Enum
const enum
as-const-Objekt
Union-Typ
Enum-Generator
Typname
Member (durch Kommas getrennt)
Erste Zahl
Enum-Stil
TypeScript
Erzeugtes JavaScript
TypeScript kopieren
JavaScript kopieren
Nutze Namen, die mit einem Buchstaben, $ oder _ beginnen und nur Buchstaben, Ziffern, $ oder _ enthalten, ohne einen Namen doppelt zu verwenden.