Wie bekomme ich Namen von Enum-Einträgen?

314

Ich möchte ein TypeScript und einen enumTyp iterieren und jeden aufgezählten Symbolnamen erhalten, z.

enum myEnum { entry1, entry2 }

for (var entry in myEnum) { 
    // use entry's name here, e.g., "entry1"
}
CalvinDale
quelle
Dieses winzige Enum-for- Paket hat getAllEnumValuesund getAllEnumKeysfür Ihren Zweck
Transang

Antworten:

254

Der von Ihnen veröffentlichte Code funktioniert. Es werden alle Mitglieder der Aufzählung ausgedruckt, einschließlich der Werte der Aufzählungsmitglieder. Zum Beispiel der folgende Code:

enum myEnum { bar, foo }

for (var enumMember in myEnum) {
   console.log("enum member: ", enumMember);
}

Druckt Folgendes:

Enum member: 0
Enum member: 1
Enum member: bar
Enum member: foo

Wenn Sie stattdessen nur die Mitgliedsnamen und nicht die Werte möchten, können Sie Folgendes tun:

for (var enumMember in myEnum) {
   var isValueProperty = parseInt(enumMember, 10) >= 0
   if (isValueProperty) {
      console.log("enum member: ", myEnum[enumMember]);
   }
}

Das druckt nur die Namen aus:

Enum-Mitglied: Bar

Enum-Mitglied: foo

Vorsichtsmaßnahme: Dies hängt geringfügig von einem Implementierungsdetail ab: TypeScript kompiliert Aufzählungen zu einem JS-Objekt, wobei die Aufzählungswerte Mitglieder des Objekts sind. Wenn TS beschließt, sie in Zukunft anders zu implementieren, könnte die oben genannte Technik brechen.

Judah Gabriel Himango
quelle
23
Um klar zu sein, funktioniert die obige Antwort ab TS 2.3 immer noch. Wenn Sie jedoch "const enum" anstelle von "enum" verwenden, funktioniert dies nur dann nicht. Die Verwendung von const enum weist TS grundsätzlich an, ein Suchen und Ersetzen durchzuführen. Jeder Ort, an dem Sie MyEnum.Foo verwenden, wird durch einen entsprechenden numerischen Wert ersetzt.
Judah Gabriel Himango
Ich denke, das +enumMember >= 0sollte daran liegen, isFinite(+enumMember)dass negative oder Gleitkommawerte auch umgekehrt abgebildet werden. ( Spielplatz )
Spenceryue
339

Obwohl die Antwort bereits gegeben ist, zeigte fast niemand auf die Dokumente

Hier ist ein Ausschnitt

enum Enum {
    A
}
let nameOfA = Enum[Enum.A]; // "A"

Beachten Sie, dass String-Enum-Mitglieder überhaupt keine umgekehrte Zuordnung erhalten.

shakram02
quelle
38
Dort heißt es auch: "Beachten Sie, dass Mitglieder der String-Aufzählung überhaupt keine umgekehrte Zuordnung erhalten."
Jbojcic
1
Wie wäre es mit Anzeigen 0oder 1aus dieser Aufzählung? export enum Octave { ZERO = 0, ONE = 1 }
Stephane
@jbojcic Geht es um die Situation : enum Enum {"A"}; let nameOfA = Enum[Enum.A];? Ab
[email protected]
Wie wäre es mit einer Schleife durch Werte?
Shioko
55

Angenommen, Sie halten sich an die Regeln und erstellen nur Aufzählungen mit numerischen Werten. Sie können diesen Code verwenden. Dies behandelt den Fall korrekt, in dem Sie einen Namen haben, der zufällig eine gültige Nummer ist

enum Color {
    Red,
    Green,
    Blue,
    "10" // wat
}

var names: string[] = [];
for(var n in Color) {
    if(typeof Color[n] === 'number') names.push(n);
}
console.log(names); // ['Red', 'Green', 'Blue', '10']
Ryan Cavanaugh
quelle
Warnung Im modernen Typoskript (tsc 2.5.2 atm) dürfen Sie nicht einmal eine numerische Zeichenfolge als Schlüssel haben. Als solches ist Himangos Antwort besser, da sie alle Fälle abdeckt und keine Nachteile hat.
srcspider
52

Für mich ist die folgende Aufzählung eine einfachere, praktischere und direktere Möglichkeit zu verstehen, was vor sich geht:

enum colors { red, green, blue };

Wird im Wesentlichen darauf umgestellt:

var colors = { red: 0, green: 1, blue: 2,
               [0]: "red", [1]: "green", [2]: "blue" }

Aus diesem Grund gilt Folgendes:

colors.red === 0
colors[colors.red] === "red"
colors["red"] === 0

Dies schafft eine einfache Möglichkeit, den Namen einer Aufzählung wie folgt zu erhalten:

var color: colors = colors.red;
console.log("The color selected is " + colors[color]);

Es bietet auch eine gute Möglichkeit, eine Zeichenfolge in einen Aufzählungswert zu konvertieren.

var colorName: string = "green";
var color: colors = colors.red;
if (colorName in colors) color = colors[colorName];

Die beiden oben genannten Situationen sind weitaus häufiger, da Sie normalerweise viel mehr am Namen eines bestimmten Werts und an der generischen Serialisierung von Werten interessiert sind.

Michael Erickson
quelle
48

Wenn Sie nur nach den Namen suchen und später wiederholen, verwenden Sie:

Object.keys(myEnum).map(key => myEnum[key]).filter(value => typeof value === 'string') as string[];
Simon
quelle
11
Oder mit der ES2017 lib:Object.values(myEnum).filter(value => typeof value === 'string') as string[];
Keine
Ich musste ein Diktat erstellen und habe Ihre Antwort als Ausgangspunkt verwendet. Wenn jemand anderes es braucht,Object.values(myEnum).filter(value => typeof value === 'string').map(key => { return {id: myEnum[key], type: key }; });
Fejs
25

Mit der aktuellen TypeScript Version 1.8.9 verwende ich typisierte Enums:

export enum Option {
    OPTION1 = <any>'this is option 1',
    OPTION2 = <any>'this is option 2'
}

mit Ergebnissen in diesem Javascript-Objekt:

Option = {
    "OPTION1": "this is option 1",
    "OPTION2": "this is option 2",
    "this is option 1": "OPTION1",
    "this is option 2": "OPTION2"
}

Ich muss also Schlüssel und Werte abfragen und nur Werte zurückgeben:

let optionNames: Array<any> = [];    
for (let enumValue in Option) {
    let optionNameLength = optionNames.length;

    if (optionNameLength === 0) {
        this.optionNames.push([enumValue, Option[enumValue]]);
    } else {
        if (this.optionNames[optionNameLength - 1][1] !== enumValue) {
            this.optionNames.push([enumValue, Option[enumValue]]);
        }
    }
}

Und ich erhalte die Optionsschlüssel in einem Array:

optionNames = [ "OPTION1", "OPTION2" ];
Philip
quelle
17

Diese Lösung funktioniert auch.

enum ScreenType {
    Edit = 1,
    New = 2,
    View = 4
}

var type: ScreenType = ScreenType.Edit;

console.log(ScreenType[type]); //Edit
Carlinhos
quelle
13

Eine weitere interessante Lösung hier verwendet ES6 Karte:

export enum Type {
  low,
  mid,
  high
}

export const TypeLabel = new Map<number, string>([
  [Type.low, 'Low Season'],
  [Type.mid, 'Mid Season'],
  [Type.high, 'High Season']
]);

VERWENDEN

console.log(TypeLabel.get(Type.low)); // Low Season
Manzapanza
quelle
10

Lassen Sie ts-enum-util( github , npm ) die Arbeit für Sie erledigen und stellen Sie viele zusätzliche typsichere Dienstprogramme bereit. Funktioniert sowohl mit Zeichenfolgen als auch mit numerischen Aufzählungen und ignoriert die numerischen Index-Reverse-Lookup-Einträge für numerische Aufzählungen ordnungsgemäß:

String enum:

import {$enum} from "ts-enum-util";

enum Option {
    OPTION1 = 'this is option 1',
    OPTION2 = 'this is option 2'
}

// type: ("OPTION1" | "OPTION2")[]
// value: ["OPTION1", "OPTION2"]
const keys= $enum(Option).getKeys();

// type: Option[]
// value: ["this is option 1", "this is option 2"]
const values = $enum(Option).getValues();

Numerische Aufzählung:

enum Option {
    OPTION1,
    OPTION2
}

// type: ("OPTION1" | "OPTION2")[]
// value: ["OPTION1", "OPTION2"]
const keys= $enum(Option).getKeys();

// type: Option[]
// value: [0, 1]
const values = $enum(Option).getValues();
Jeff Lau
quelle
9

Ab TypeScript 2.4 würde die Aufzählung den Schlüssel als Mitglied nicht mehr enthalten. Quelle aus der TypeScript-Readme-Datei

Die Einschränkung besteht darin, dass durch Zeichenfolgen initialisierte Aufzählungen nicht rückwärts zugeordnet werden können, um den ursprünglichen Namen des Aufzählungsmitglieds zu erhalten. Mit anderen Worten, Sie können keine Farben ["ROT"] schreiben, um die Zeichenfolge "Rot" zu erhalten.

Meine Lösung:

export const getColourKey = (value: string ) => {
    let colourKey = '';
    for (const key in ColourEnum) {
        if (value === ColourEnum[key]) {
            colourKey = key;
            break;
        }
    }
    return colourKey;
};
kitko112
quelle
8

Sie können das enum-valuesPaket verwenden, das ich geschrieben habe, als ich das gleiche Problem hatte:

Git: Enum-Werte

var names = EnumValues.getNames(myEnum);
Slava Shpitalny
quelle
3
Sie beantworten die Frage nicht wirklich, es wäre besser, Ihre Antwort mit Code / etc zu dokumentieren, aber ich fand das Paket nützlich.
Lucuma
7

Basierend auf einigen Antworten oben habe ich diese typsichere Funktionssignatur gefunden:

export function getStringValuesFromEnum<T>(myEnum: T): keyof T {
  return Object.keys(myEnum).filter(k => typeof (myEnum as any)[k] === 'number') as any;
}

Verwendungszweck:

enum myEnum { entry1, entry2 };
const stringVals = getStringValuesFromEnum(myEnum);

die Art von stringValsist'entry1' | 'entry2'

Sehen Sie es in Aktion

Dmitry Efimenko
quelle
1
Die Funktion sollte zurückkehren (keyof T)[]statt keyof T. Außerdem verhindert dies, dass exportIhr Spielplatz funktioniert.
Joald
7

Es scheint, dass keine der Antworten hier mit String-Enums im -mode funktioniert strict.

Betrachten Sie die Aufzählung als:

enum AnimalEnum {
  dog = "dog", cat = "cat", mouse = "mouse"
}

Der Zugriff mit AnimalEnum["dog"]kann zu einem Fehler führen wie:

Element implicitly has an 'any' type because expression of type 'any' can't be used to index type 'typeof AnimalEnum'.ts(7053).

Richtige Lösung für diesen Fall, schreiben Sie es als:

AnimalEnum["dog" as keyof typeof AnimalEnum]
Coyer
quelle
Geniale Lösung für die Verwendung keyofmit typeof! Eine andere Lösung scheint ziemlich undurchsichtig zu sein, aber ich denke, Typescript muss DX - Developer Experience für Enum
Shaung Cheng
5

Ich denke, der beste Weg ist, einfach die gewünschten Aufzählungswerte zu deklarieren. Auf diese Weise ist der Zugriff auf sie sauber und hübsch (jedes Mal).

enum myEnum { entry1 = 'VALUE1', entry2 = 'VALUE2' }

for (var entry in myEnum) { 
    console.log(entry);
}

wird herstellen:

VALUE1
VALUE2
stemadsen
quelle
5

Laut TypeScript-Dokumentation können wir dies über Enum mit statischen Funktionen tun.

Holen Sie sich Enum Name mit statischen Funktionen

enum myEnum { 
    entry1, 
    entry2 
}

namespace myEnum {
    export function GetmyEnumName(m: myEnum) {
      return myEnum[m];
    }
}


now we can call it like below
myEnum.GetmyEnumName(myEnum.entry1);
// result entry1 

Weitere Informationen zu Enum mit statischer Funktion finden Sie unter folgendem Link: https://basarat.gitbooks.io/typescript/docs/enums.html

Shahid Ahmad
quelle
4

Die einzige Lösung, die in allen Fällen für mich funktioniert (auch wenn Werte Zeichenfolgen sind), ist die folgende:

var enumToString = function(enumType, enumValue) {
    for (var enumMember in enumType) {
        if (enumType[enumMember]==enumValue) return enumMember
    }
}
user2080105
quelle
4

Alte Frage, aber warum keine constObjektkarte verwenden?

Anstatt dies zu tun:

enum Foo {
    BAR = 60,
    EVERYTHING_IS_TERRIBLE = 80
}

console.log(Object.keys(Foo))
// -> ["60", "80", "BAR", "EVERYTHING_IS_TERRIBLE"]
console.log(Object.values(Foo))
// -> ["BAR", "EVERYTHING_IS_TERRIBLE", 60, 80]

Tun Sie dies (achten Sie auf die as constBesetzung):

const Foo = {
    BAR: 60,
    EVERYTHING_IS_TERRIBLE: 80
} as const

console.log(Object.keys(Foo))
// -> ["BAR", "EVERYTHING_IS_TERRIBLE"]
console.log(Object.values(Foo))
// -> [60, 80]
Gabriel De Oliveira Rohden
quelle
Korrigieren Sie mich, wenn ich falsch liege, aber console.log(Object.keys(Foo))im ersten Beispiel nur zurückkommt ["BAR", "EVERYTHING_IS_TERRIBLE"]..
Peter
@Peter werfen Sie einen Blick hier auf den Spielplatz , öffnen Sie einfach die Konsole und klicken Sie auf Ausführen. Zumindest für mich druckt es["60", "80", "BAR", "EVERYTHING_IS_TERRIBLE"]
Gabriel De Oliveira Rohden
1
Es scheint Ihr Recht zu sein. Wenn Sie von Zahlen zu Zeichenfolgen wechseln, erhalten Sie die erwartete Ausgabe. Ich habe keine Ahnung, warum Typoskript Zeichenfolgen und Zahlen in Aufzählungen unterschiedlich behandelt.
Peter
4

Ich habe diese Frage gefunden, indem ich nach "TypeScript iteriere über Enum-Schlüssel" gesucht habe. Ich möchte also nur eine Lösung veröffentlichen, die in meinem Fall für mich funktioniert. Vielleicht hilft es auch jemandem.

Mein Fall ist der folgende: Ich möchte über jeden Aufzählungsschlüssel iterieren, dann einige Schlüssel filtern und dann auf ein Objekt zugreifen, das Schlüssel als berechnete Werte aus der Aufzählung enthält. So mache ich es also ohne TS-Fehler.

    enum MyEnum = { ONE = 'ONE', TWO = 'TWO' }
    const LABELS = {
       [MyEnum.ONE]: 'Label one',
       [MyEnum.TWO]: 'Label two'
    }


    // to declare type is important - otherwise TS complains on LABELS[type]
    // also, if replace Object.values with Object.keys - 
    // - TS blames wrong types here: "string[] is not assignable to MyEnum[]"
    const allKeys: Array<MyEnum> = Object.values(MyEnum)

    const allowedKeys = allKeys.filter(
      (type) => type !== MyEnum.ONE
    )

    const allowedLabels = allowedKeys.map((type) => ({
      label: LABELS[type]
    }))
Alendorff
quelle
3

Ich habe eine EnumUtil-Klasse geschrieben, die eine Typprüfung anhand des Enum-Werts durchführt:

export class EnumUtils {
  /**
   * Returns the enum keys
   * @param enumObj enum object
   * @param enumType the enum type
   */
  static getEnumKeys(enumObj: any, enumType: EnumType): any[] {
    return EnumUtils.getEnumValues(enumObj, enumType).map(value => enumObj[value]);
  }

  /**
   * Returns the enum values
   * @param enumObj enum object
   * @param enumType the enum type
   */
  static getEnumValues(enumObj: any, enumType: EnumType): any[] {
    return Object.keys(enumObj).filter(key => typeof enumObj[key] === enumType);
  }
}

export enum EnumType {
  Number = 'number',
  String = 'string'
}

Wie man es benutzt:

enum NumberValueEnum{
  A= 0,
  B= 1
}

enum StringValueEnum{
  A= 'A',
  B= 'B'
}

EnumUtils.getEnumKeys(NumberValueEnum, EnumType.number);
EnumUtils.getEnumValues(NumberValueEnum, EnumType.number);

EnumUtils.getEnumKeys(StringValueEnum, EnumType.string);
EnumUtils.getEnumValues(StringValueEnum, EnumType.string);

Ergebnis für NumberValueEnum-Schlüssel: ["A", "B"]

Ergebnis für NumberValueEnum-Werte: [0, 1]

Ergebnis für StringValueEnumkeys: ["A", "B"]

Ergebnis für StringValueEnumvalues: ["A", "B"]

Arnold Vakaria
quelle
2

Ich finde diese Lösung eleganter:

for (let val in myEnum ) {

 if ( isNaN( parseInt( val )) )
     console.log( val );
}

Es zeigt an:

bar 
foo
Anthony Brenelière
quelle
2

Meine Aufzählung ist wie folgt:

export enum UserSorting {
    SortByFullName = "Sort by FullName", 
    SortByLastname = "Sort by Lastame", 
    SortByEmail = "Sort by Email", 
    SortByRoleName = "Sort by Role", 
    SortByCreatedAt = "Sort by Creation date", 
    SortByCreatedBy = "Sort by Author", 
    SortByUpdatedAt = "Sort by Edit date", 
    SortByUpdatedBy = "Sort by Editor", 
}

Wenn Sie dies tun, geben Sie undefiniert zurück :

UserSorting[UserSorting.SortByUpdatedAt]

Um dieses Problem zu beheben, wähle ich einen anderen Weg, um es mit einem Rohr zu tun:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
    name: 'enumKey'
})
export class EnumKeyPipe implements PipeTransform {

  transform(value, args: string[] = null): any {
    let enumValue = args[0];
    var keys = Object.keys(value);
    var values = Object.values(value);
    for (var i = 0; i < keys.length; i++) {
      if (values[i] == enumValue) {
        return keys[i];
      }
    }
    return null;
    }
}

Und um es zu benutzen:

return this.enumKeyPipe.transform(UserSorting, [UserSorting.SortByUpdatedAt]);
Cedric Arnould
quelle
2

Wenn Sie eine Aufzählung haben

enum Diet {
  KETO = "Ketogenic",
  ATKINS = "Atkins",
  PALEO = "Paleo",
  DGAF = "Whatever"
}

Dann können Sie Schlüssel und Werte erhalten wie:

Object.keys(Diet).forEach((d: Diet) => {
  console.log(d); // KETO
  console.log(Diet[d]) // Ketogenic
});
clu
quelle
Dies verursacht einen Fehler: Argument of type '(d: Diet) => void' is not assignable to parameter of type '(value: string, index: number, array: string[]) => void'. Types of parameters 'd' and 'value' are incompatible. Type 'string' is not assignable to type 'MyEnum'.(2345)
11.
1

Ich habe eine Hilfsfunktion geschrieben, um eine Aufzählung aufzulisten:

static getEnumValues<T extends number>(enumType: {}): T[] {
  const values: T[] = [];
  const keys = Object.keys(enumType);
  for (const key of keys.slice(0, keys.length / 2)) {
    values.push(<T>+key);
  }
  return values;
}

Verwendungszweck:

for (const enumValue of getEnumValues<myEnum>(myEnum)) {
  // do the thing
}

Die Funktion gibt etwas zurück, das leicht aufgezählt werden kann, und wandelt sich auch in den Aufzählungstyp um.

Russell Phillips
quelle
0

Mit einer aktuellen TypeScript-Version können Sie Funktionen wie diese verwenden, um die Aufzählung einem Datensatz Ihrer Wahl zuzuordnen. Beachten Sie, dass Sie mit diesen Funktionen keine Zeichenfolgenwerte definieren können, da sie nach Schlüsseln mit einem Wert suchen, der eine Zahl ist.

enum STATES {
  LOGIN,
  LOGOUT,
}

export const enumToRecordWithKeys = <E extends any>(enumeration: E): E => (
  Object.keys(enumeration)
    .filter(key => typeof enumeration[key] === 'number')
    .reduce((record, key) => ({...record, [key]: key }), {}) as E
);

export const enumToRecordWithValues = <E extends any>(enumeration: E): E => (
  Object.keys(enumeration)
    .filter(key => typeof enumeration[key] === 'number')
    .reduce((record, key) => ({...record, [key]: enumeration[key] }), {}) as E
);

const states = enumToRecordWithKeys(STATES)
const statesWithIndex = enumToRecordWithValues(STATES)

console.log(JSON.stringify({
  STATES,
  states,
  statesWithIndex,
}, null ,2));

// Console output:
{
  "STATES": {
    "0": "LOGIN",
    "1": "LOGOUT",
    "LOGIN": 0,
    "LOGOUT": 1
  },
  "states": {
    "LOGIN": "LOGIN",
    "LOGOUT": "LOGOUT"
  },
  "statesWithIndex": {
    "LOGIN": 0,
    "LOGOUT": 1
  }
}
größten1
quelle
0

Hier gibt es bereits viele Antworten, aber ich denke, ich werde meine Lösung trotzdem auf den Stapel werfen.

TypeScript-Spielplatz

enum AccountType {
  Google = 'goo',
  Facebook = 'boo',
  Twitter = 'wit',
}

type Key = keyof typeof AccountType // "Google" | "Facebook" | "Twitter"

// this creates a POJO of the enum "reversed" using TypeScript's Record utility
const reversed = (Object.keys(AccountType) as Key[]).reduce((acc, key) => {
  acc[AccountType[key]] = key
  return acc
}, {} as Record<AccountType, string>)

Zur Klarheit:

/*
 * reversed == {
 *   "goo": "Google",
 *   "boo": "Facebook",
 *   "wit": "Twitter",
 * }
 * reversed[AccountType.Google] === "Google" 👍
 */

Referenz für TypeScript Record

Eine nette Hilfsfunktion:

const getAccountTypeName = (type: AccountType) => {
  return reversed[type]
};

// getAccountTypeName(AccountType.Twitter) === 'Twitter'
Chance
quelle
0

Um die Liste der Aufzählungswerte zu erhalten, müssen Sie Folgendes verwenden:

enum AnimalEnum {
  DOG = "dog", 
  CAT = "cat", 
  MOUSE = "mouse"
}

Object.values(AnimalEnum);
Radu Linu
quelle
-1

Es ist nicht genau die Antwort auf Ihre Frage, aber es ist ein Trick, um Ihr Problem anzugehen.

export module Gender {

  export enum Type {
    Female = 1,
    Male = 2
  };

  export const List = Object.freeze([
    Type[Type.Female] ,
    Type[Type.Male]
  ]);

}

Sie können Ihr Listenmodell beliebig erweitern.

export const List = Object.freeze([
    { name: Type[Type.Female], value: Type.Female } ,
    { name: Type[Type.Male], value: Type.Male }
  ]);

Jetzt können Sie es folgendermaßen verwenden:

for(const gender of Gender.List){
  console.log(gender.name);
  console.log(gender.value);
}

oder:

if(i === Gender.Type.Male){
  console.log("I am a man.");
}
Pedram Ahmadpour
quelle