it-swarm.com.de

Wie konvertiere ich einen String in TypeScript nach enum?

Ich habe die folgende Enumeration in TypeScript definiert:

enum Color{
    Red, Green
}

Jetzt in meiner Funktion erhalte ich Farbe als Zeichenfolge. Ich habe den folgenden Code ausprobiert:

var green= "Green";
var color : Color = <Color>green; // Error: can't convert string to enum

Wie kann ich diesen Wert in eine Aufzählung umwandeln?

226
Amitabh

Aufzählungen in TypeScript 0.9 basieren auf Zeichenfolge und Zahl. Sie sollten keine Typzusicherung für einfache Konvertierungen benötigen:

enum Color{
    Red, Green
}

// To String
 var green: string = Color[Color.Green];

// To Enum / number
var color : Color = Color[green];

Online ausprobieren

Ich habe eine Dokumentation zu diesem und anderen Enum-Mustern in meinem OSS-Buch: https://basarat.gitbooks.io/TypeScript/content/docs/enums.html

331
basarat

Ab TypeScript 2.1 sind Zeichenfolgenschlüssel in Aufzählungen stark typisiert. keyof typeof wird verwendet, um Informationen über verfügbare Zeichenfolgenschlüssel abzurufen ( 1 ):

enum Color{
    Red, Green
}

let typedColor: Color = Color.Green;
let typedColorString: keyof typeof Color = "Green";

// Error "Black is not assignable ..." (indexing using Color["Black"] will return undefined runtime)
typedColorString = "Black";

// Error "Type 'string' is not assignable ..." (indexing works runtime)
let letColorString = "Red";
typedColorString = letColorString;

// Works fine
typedColorString = "Red";

// Works fine
const constColorString = "Red";
typedColorString = constColorString

// Works fine (thanks @SergeyT)
let letColorString = "Red";
typedColorString = letColorString as keyof typeof Color;

typedColor = Color[typedColorString];

https://www.typescriptlang.org/docs/handbook/advanced-types.html#index-types

89
Victor

Diese Anmerkung 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 ausgegeben hat, der ungefähr dem Ergebnis "Zeichenfolge kann nicht in Farbe konvertiert werden" entspricht. Verwenden Sie dazu den folgenden Code:

var colorId = myOtherObject.colorId; // value "Green";
var color: Color = <Color>Color[colorId]; // TSC error here: Cannot convert string to Color.

Ich stellte fest, dass die Inferenz des Compilertyps verwirrt wurde und dachte, dass colorId ein Aufzählungswert und keine ID ist. Um das Problem zu beheben, musste ich die ID als String umwandeln:

var colorId = <string>myOtherObject.colorId; // Force string value here
var color: Color = Color[colorId]; // Fixes lookup here.

Ich bin nicht sicher, was das Problem verursacht hat, aber ich werde diese Notiz hier lassen, falls jemand auf dasselbe Problem stößt, das ich gemacht habe.

26
Sly_cardinal

Wenn Sie sicher sind, dass eine Eingabezeichenfolge genau mit Color enum übereinstimmt, verwenden Sie Folgendes:

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

Verwenden Sie für den Fall, dass eine Eingabezeichenfolge möglicherweise nicht mit Enum übereinstimmt:

const mayBeColor: Color | undefined = (<any>Color)["WrongInput"];
if (mayBeColor !== undefined){
     // TypeScript will understand that mayBeColor is of type Color here
}

Spielplatz


Wenn wir enum nicht in <any> Umwandeln, zeigt TypeScript den Fehler an:

Das Element hat implizit einen Typ "any", da der Indexausdruck nicht vom Typ "number" ist.

Dies bedeutet, dass der TypeScript-Aufzählungstyp standardmäßig mit Zahlenindizes arbeitet, d. H. let c = Color[0], Jedoch nicht mit Zeichenfolgenindizes wie let c = Color["string"]. Dies ist eine vom Microsoft-Team bekannte Einschränkung für das allgemeinere Problem Objektzeichenfolgenindizes.

25
Artru

Ich habe es funktioniert mit dem folgenden Code.

var green= "Green";
var color : Color= <Color>Color[green];
21
Amitabh

Ich bin auch auf den gleichen Compilerfehler gestoßen. Nur eine geringfügig kürzere Variante von Sly_cardinals Ansatz.

var color: Color = Color[<string>colorId];
12
Chris

Wenn der TypeScript-Compiler weiß, dass der Variablentyp ein String ist, funktioniert Folgendes:

let colorName : string = "Green";
let color : Color = Color[colorName];

Andernfalls sollten Sie es explizit in einen String konvertieren (um Compiler-Warnungen zu vermeiden):

let colorName : any = "Green";
let color : Color = Color["" + colorName];

Zur Laufzeit funktionieren beide Lösungen.

9
Luka
enum Color{
    Red, Green
}

// To String
 var green: string = Color[Color.Green];

// To Enum / number
var color : Color = Color[green as keyof typeof Color]; //Works with --noImplicitAny

Dieses Beispiel funktioniert mit --noImplicitAny in TypeScript

Quellen:
https://github.com/Microsoft/TypeScript/issues/13775#issuecomment-276381229https://www.typescriptlang.org/docs/handbook/advanced -types.html # Indextypen

6
Jonas

Diese Frage enthält viele unterschiedliche Informationen. Lassen Sie uns die gesamte Implementierung von TypeScript 2.x + in Nicks Handbuch zur Verwendung von Enums in Modellen mit TypeScript behandeln.

Dieses Handbuch richtet sich an: Benutzer, die clientseitigen Code erstellen, der eine Reihe bekannter Zeichenfolgen vom Server aufnimmt, die auf Clientseite bequem als Enum-Code modelliert werden.

Definieren Sie die Aufzählung

Beginnen wir mit der Aufzählung. Es sollte ungefähr so ​​aussehen:

export enum IssueType {
  REPS = 'REPS',
  FETCH = 'FETCH',
  ACTION = 'ACTION',
  UNKNOWN = 'UNKNOWN',
}

Zwei wichtige Punkte hier:

  1. Wir deklarieren diese explizit als String-Backed Enum-Fälle, wodurch wir sie mit Strings instanziieren können, nicht mit anderen, nicht zusammenhängenden Zahlen.

  2. Wir haben eine Option hinzugefügt, die in unserem Servermodell möglicherweise vorhanden ist oder nicht: UNKNOWN. Dies kann als undefined behandelt werden, wenn Sie es vorziehen, aber ich vermeide | undefined nach Möglichkeit auf Typen, um die Handhabung zu vereinfachen.

Das Tolle an einem UNKNOWN -Fall ist, dass Sie im Code wirklich offensichtlich sein können und Stile für unbekannte Enum-Fälle hellrot und blinkend gestalten können, sodass Sie wissen, dass Sie etwas nicht richtig handhaben.

Analysieren Sie die Aufzählung

Möglicherweise verwenden Sie diese Enumeration, die in ein anderes Modell eingebettet ist, oder ganz alleine, aber Sie müssen die String-y-typisierte Enumeration von JSON oder XML (ha) in Ihr stark typisiertes Gegenstück zerlegen. Wenn dieser Parser in ein anderes Modell eingebettet ist, befindet er sich im Klassenkonstruktor.

parseIssueType(typeString: string): IssueType {
  const type = IssueType[typeString];
  if (type === undefined) {
    return IssueType.UNKNOWN;
  }

  return type;
}

Wenn die Aufzählung richtig analysiert wird, wird sie als der richtige Typ enden. Andernfalls wird es undefined sein und Sie können es abfangen und Ihren Fall UNKNOWN zurückgeben. Wenn Sie es vorziehen, undefined als unbekannten Fall zu verwenden, können Sie einfach jedes Ergebnis aus dem versuchten Aufzählungsparsing zurückgeben.

Von dort aus müssen Sie nur noch die Analysefunktion und Ihre neu erstellte, stark typisierte Variable verwenden.

const strongIssueType: IssueType = parseIssueType('ACTION');
// IssueType.ACTION
const wrongIssueType: IssueType = parseIssueType('UNEXPECTED');
// IssueType.UNKNOWN
5
Nick

Ich musste wissen, wie man Enum-Werte durchläuft (testete viele Permutationen mehrerer Enums) und fand, dass dies gut funktioniert:

export enum Environment {
    Prod = "http://asdf.com",
    Stage = "http://asdf1234.com",
    Test = "http://asdfasdf.example.com"
}

Object.keys(Environment).forEach((environmentKeyValue) => {
    const env = Environment[environmentKeyValue as keyof typeof Environment]
    // env is now equivalent to Environment.Prod, Environment.Stage, or Environment.Test
}
2
mikeb

Aufzählung

enum MyEnum {
    First,
    Second,
    Three
}

Beispielnutzung

const parsed = Parser.parseEnum('FiRsT', MyEnum);
// parsed = MyEnum.First 

const parsedInvalid= Parser.parseEnum('other', MyEnum);
// parsedInvalid = undefined

Groß-/Kleinschreibung ignorieren

class Parser {
    public static parseEnum<T>(value: string, enumType: T): T[keyof T] | undefined {
        if (!value) {
            return undefined;
        }

        for (const property in enumType) {
            const enumMember = enumType[property];
            if (typeof enumMember === 'string') {
                if (enumMember.toUpperCase() === value.toUpperCase()) {
                    const key = enumMember as string as keyof typeof enumType;
                    return enumType[key];
                }
            }
        }
        return undefined;
    }
}

Versuche dies

var color: Color = (Farbe wie jede andere) ["Green];

Das funktioniert gut für 3.5.3 Version

1
Oyeme

Aufzählungen, die auf diese Weise erstellt wurden, werden in ein Objekt kompiliert, in dem sowohl Forward-Zuordnungen (name -> value) Als auch Reverse-Zuordnungen (value -> name) Gespeichert sind. Wie wir aus diesem chrome devtools screenshot sehen können:

enter image description here

Hier ist ein Beispiel dafür, wie Dual-Mapping funktioniert und wie von einem zum anderen umgewandelt wird:

enum Color{
    Red, Green
}
// To Number
var greenNr: number = Color['Green'];
console.log(greenNr); // logs 1

// To String
var greenString: string = Color[Color['Green']];  // or Color[Color[1]
console.log(greenString); // logs Green

// In your example

// recieve as Color.green instead of the string green
var green: string = Color[Color.Green];  

// obtain the enum number value which corresponds to the Color.green property
var color: Color = (<any>Color)[green];  

console.log(color); // logs 1
0