715 Stimmen

Wie konvertiere ich einen String in ein Enum in TypeScript?

Ich habe das folgende Enum in TypeScript definiert:

enum Color{
    Rot, Grün
}

Jetzt erhalte ich in meiner Funktion die Farbe als Zeichenkette. Ich habe den folgenden Code versucht:

var grün = "Grün";
var farbe : Color = grün; // Fehler: kann Zeichenkette nicht in Enum konvertieren

Wie kann ich diesen Wert in ein Enum konvertieren?

85voto

Artur A Punkte 5541

Typescript 1.x

Wenn Sie sicher sind, dass ein Eingabestring mit dem Color-Enum genau übereinstimmt, verwenden Sie:

const color: Color = (Color)["Red"];

Im Falle, dass ein Eingabestring nicht mit dem Enum übereinstimmen kann, verwenden Sie:

const mayBeColor: Color | undefined = (Color)["WrongInput"];
if (mayBeColor !== undefined){
     // TypeScript wird hier verstehen, dass mayBeColor vom Typ Color ist
}

[Playground](http://www.typescriptlang.org/play/#src=enum%20Color%7B%0A%20%20%20%20Red%2C%20Green%0A%7D%0Aconst%20color%3A%20Color%20%3D%20%3Cany%3EColor%5B%22Green%22%5D%3B%0Aconsole.log(%22color%3A%20%22%20%2B%20color)%3B%0A%0Aconst%20mayBeColor%3A%20Color%20%7C%20undefined%20%3D%20%3Cany%3EColor%5B%22WrongInput%22%5D%3B%0Aconsole.log(%22nicht vorhandene Farbe%3A%20%22%20%2B%20mayBeColor)%3B%0A%0Aconst%20mayBeColor2%3A%20Color%20%7C%20undefined%20%3D%20%3Cany%3EColor%5B%22Green%22%5D%3B%0Aconsole.log(%22vorhandene Farbe%3A%20%22%2BmayBeColor2)%3B)


Wenn wir enum nicht auf den Typ casten, zeigt TypeScript den Fehler:

Element hat implizit den Typ 'any', weil der Indexausdruck nicht vom Typ 'number' ist.

Das bedeutet, dass der TypeScript Enum-Typ standardmäßig mit Nummernindizes funktioniert, z.B. let c = Color[0], aber nicht mit Zeichenfolgenindizes wie let c = Color["string"]. Dies ist eine bekannte Einschränkung des Microsoft-Teams für das allgemeinere Problem Objektzeichenindizes.

Typescript 2.x-4x

TypeScript hat zum Konzept keyof typeof gewechselt.

Wenn jemand Zeichenwert-Enums verwendet:

enum Color {
  Green = "GRN",
  Red = "RD"
}

gibt es eine Sprachlösung, um Schlüssel zu Werten abzubilden (Color.Green -> "GRN") nur durch den Zugriff auf ein Enum-Mitglied, aber es gibt keinen einfachen Weg, das Gegenteil zu tun ("GRN" -> Color.Green). Aus Reverse-Mapping:

Beachten Sie, dass String-Enum-Mitglieder überhaupt keine rückwärts Mapping generiert bekommen.

Eine mögliche Lösung besteht darin, Werte manuell zu überprüfen und den Wert in das Enum zu casten. Bitte beachten Sie, dass dies nur mit String-Enums funktioniert.

function enumFromStringValue (enm: { [s: string]: T}, value: string): T | undefined {
  return (Object.values(enm) as unknown as string[]).includes(value)
    ? value as unknown as T
    : undefined;
}

enumFromStringValue(Color, "RD"); // Color.Red
enumFromStringValue(Color, "UNKNOWN"); // undefined
enumFromStringValue(Color, "Red"); // undefined

39voto

ford04 Punkte 56200

Einfachster Ansatz

enum Color { Red, Green }

const c1 = Color["Red"]
const redStr = "Red" // wichtig: Verwenden Sie `const`, nicht veränderbares `let`
const c2 = Color[redStr]

Dies funktioniert sowohl für numerische als auch für Zeichenketten enums. Es ist nicht erforderlich, eine Typzuweisung zu verwenden.

Unbekannte enum Zeichenketten

Einfache, unsichere Variante

const redStrWide: string = "Red" // weite, nicht spezifisch typisierte Zeichenkette
const c3 = Color[redStrWide as keyof typeof Color]

Sichere Variante mit Überprüfungen

const isEnumName = (str: string, _enum: T): str is Extract =>
    str in _enum
const enumFromName = (name: string, _enum: T) => {
    if (!isEnumName(name, _enum)) throw Error() // hier schnell scheitern als Beispiel
    return _enum[name]
}
const c4 = enumFromName(redStrWide, Color)

Umwandlung von Zeichenketteneinheiten

Zeichenkettenenums haben keine umgekehrte Zuordnung (im Gegensatz zu numerischen). Wir können einen Lookup-Helfer erstellen, um einen Enum-Wert in Zeichenkette in einen Enum-Typ umzuwandeln:

enum ColorStr { Red = "red", Green = "green" }

const c5_by_name = ColorStr["Red"] //  dies funktioniert
const c5_by_value_error = ColorStr["red"] //  , aber dies nicht

const enumFromValue = >(val: string, _enum: T) => {
    const enumName = (Object.keys(_enum) as Array).find(k => _enum[k] === val)
    if (!enumName) throw Error() // hier schnell scheitern als Beispiel
    return _enum[enumName]
}

const c5 = enumFromValue("red", ColorStr)

Beispiel im Playground

34voto

Amitabh Punkte 54879

Ich habe es zum Laufen gebracht, indem ich den folgenden Code verwendet habe.

var grün = "Grün";
var farbe: Farbe = Color[grün];

33voto

Sly_cardinal Punkte 11100

Diese Notiz bezieht sich auf basarats Antwort, nicht auf die ursprüngliche Frage.

Ich hatte ein seltsames Problem in meinem eigenen Projekt, bei dem der Compiler einen Fehler in etwa "kann String nicht in Farbe umwandeln" ausgab, wenn er den Code verwendete:

var colorId = myOtherObject.colorId; // Wert "Grün";
var color: Color = Color[colorId]; // TSC Fehler hier: Kann String nicht in Farbe umwandeln.

Ich fand heraus, dass die Typinferenz des Compilers durcheinander geriet und dachte, dass colorId ein Enum-Wert und kein ID war. Um das Problem zu beheben, musste ich die ID als String casten:

var colorId = myOtherObject.colorId; // Erzwinge String-Wert hier
var color: Color = Color[colorId]; // Behebt das Lookup hier.

Ich weiß nicht, was das Problem verursacht hat, aber ich lasse diese Notiz hier für den Fall, dass jemand auf dasselbe Problem stößt wie ich.

19voto

Luka Punkte 1535

Wenn der TypeScript-Compiler weiß, dass der Typ der Variable ein String ist, dann funktioniert dies:

let colorName : string = "Grün";
let color : Color = Color[colorName];

Sonst sollte es explizit in einen String konvertiert werden (um Compilerwarnungen zu vermeiden):

let colorName : any = "Grün";
let color : Color = Color["" + colorName];

Zur Laufzeit funktionieren beide Lösungen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X