TL;DR: Entweder:
- Erstellen Sie eine Funktion, die den Stringwert analysiert und in ein Enum konvertiert.
- Wenn Sie den Schlüsselnamen basierend auf dem Wert benötigen, verwenden Sie kein TS-Enum.
Zuerst einmal ist ein Enum eine Zuordnung zwischen einem menschenlesbaren Namen und einem Wert, dafür ist es gemacht.
Standardwerte: TS stellt standardmäßig sicher, dass Sie für die definierten Schlüssel des Enums einen eindeutigen Wert haben.
Dies
enum Color {
Rot, Grün
}
ist äquivalent zu
enum Color {
Rot = 0,
Grün = 1
}
Der transpilierte JS-Code beider wird sein
"use strict";
var Color;
(function (Color) {
Color[Color["Rot"] = 0] = "Rot";
Color[Color["Grün"] = 1] = "Grün";
})(Color || (Color = {}));
Da dies unlesbar ist, hier ist das resultierende Objekt, sobald erstellt:
{0: 'Rot', 1: 'Grün', Rot: 0, Grün: 1}
Dieses Objekt hat String- und Nummereigenschaften (es kann keine Kollision geben, da Sie keinen Enum-Schlüssel als Zahl definieren können). TS ist cool genug, um ein Objekt zu generieren, das sowohl die Zuordnung Schlüssel -> Wert als auch Wert -> Schlüssel enthält.
Danke Gott, dies ist eine bijektive Zuordnung, d.h. ein jeder einzigartige Wert hat seinen einzigartigen Schlüssel (und umgekehrt gilt dies auch)
Jetzt kommen die Probleme, was ist, wenn ich den gleichen Wert erzwingen würde?
enum Color {
Rot = 0,
Grün = 0
}
Dies ist das resultierende erstellte JS-Objekt
{0: 'Grün', Rot: 0, Grün: 0}
Wir haben die Bijektivität nicht mehr (das ist surjektiv), es gibt keine magische Zuordnung 0 : ['Grün', 'Rot']
. Nur 0 : 'Grün'
und wir haben das 0 : 'Rot'
verloren
Fazit: TS wird immer versuchen, die umgekehrte Zuordnung (Wert -> Schlüssel) zu setzen, wenn die Werte Zahlen sind.
Wie Sie vielleicht wissen, können Sie auch Zeichenfolgenwerte innerhalb eines Enums definieren, lassen Sie uns nur den Wert Grün auf "Green" ändern
enum Color {
Rot = 0,
Grün = "GRÜN"
}
Hier ist das resultierende JS-Objekt
{0: 'Rot', Rot: 0, Grün: 'GRÜN'}
Wie Sie sehen können, generiert Typescript nicht die Zuordnung Wert -> Schlüssel. Und es wird es nicht tun, weil es zu einer Kollision zwischen einem Wert und einem Schlüsselnamen kommen könnte. Denken Sie daran: ein Schlüssel kann keine Zahl sein, daher besteht kein Kollisionsrisiko, wenn der Wert eine Zahl ist.
Dies lässt Sie verstehen, dass Sie sich nicht auf die Zuordnung Wert -> Schlüssel eines Enums verlassen sollten. Die Zuordnung könnte einfach nicht existieren oder ungenau sein.
Wieder einmal sollte ein Enum als menschenlesbarer Name für einen Wert betrachtet werden. In einigen Fällen wird TS überhaupt keine umgekehrte Zuordnung generieren. Dies ist der Fall, wenn Sie ein Enum const definieren.
Ein const-Enum ist ein reines Kompilierzeit-Enum. TS wird die Verwendung des Enums durch seinen entsprechenden Wert bei der Transpilierung ersetzen
Zum Beispiel:
const enum Color {
Rot = 0,
Grün = "GRÜN"
}
wird transpiliert zu
"use strict";
Also um es kurz zu machen… nichts, weil "use strict"; nicht einmal mit dem übereinstimmt, was wir geschrieben haben.
Hier ist dasselbe Beispiel mit einer Verwendung:
const enum Color {
Rot = 0,
Grün = "GRÜN"
}
console.log(Color.Grün);
wird transpiliert zu
"use strict";
console.log("GRÜN" /* Green */);
Wie Sie sehen können, wird Color.Grün durch "GREEN" am Transpiler ersetzt.
Zurück zur ursprünglichen Frage, wie konvertieren Sie also eine Zeichenfolge in ein Enum?
Parser-Lösung: Es tut mir leid, aber die einzige saubere Methode, die ich empfehle, ist das Schreiben einer Funktion; die Verwendung eines switch case ist eine kluge Methode, um dies zu erreichen.
Funktion parseColorName(color: string): Color {
switch (color) {
case 'Rot': return Color.Rot;
case 'Grün': return Color.Grün;
default: throw new Error('Unbekannte Farbe');
}
}
Benutzerdefinierte Enum-Lösung:
Beachten Sie, dass TS-Enums undurchsichtig sind, was bedeutet, dass es keine Möglichkeit für den Compiler gibt, den Wert ordnungsgemäß zu typisieren. Aus diesem Grund (und insbesondere wenn Sie die Rückwärtszuordnung verwenden müssen) würde ich empfehlen, Ihr eigenes Enum wie folgt zu erstellen:
export const Farbtyp = {
ROT: 'Rot',
GRÜN: 'Grün',
} as const;
export type Farbtyp = typeof Farbtyp[keyof typeof Farbtyp];
Das Folgende ist sicher (color
kann nur einen gültigen bekannten Wert annehmen). Kurz gesagt, Sie verlassen sich auf Zeichenfolgenunionen anstelle eines Enum-Werts.
const farbe: Farbtyp = "Grün";
// Und wenn Sie eine Farbe aus dem Enumwert erstellen müssen:
const eineAndereFarbe: Farbtyp = Farbtyp.ROT;