Как получить имена записей перечислений TypeScript?

184

Я хотел бы знать, как итерировать перечисление TypeScript и каждое перечисляемое имя символа.

например.

enum myEnum { entry1, entry2 }

for (var entry in myEnum) { 
    // use entry name here, e.g., "entry1"
}
Теги:
enums

20 ответов

146
Лучший ответ

Код, который вы опубликовали, будет работать; он распечатает все члены перечисления, включая значения членов перечисления. Например, следующий код:

enum myEnum { bar, foo }

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

Выведет следующее:

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

Если вам нужны только имена членов, а не значения, вы можете сделать что-то вроде этого:

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

Это напечатает только имена:

Член enum: bar

Участник enum: foo

Предостережение: это немного зависит от детали реализации: TypeScript скомпилирует перечисления в объект JS с значениями перечисления, являющимися членами объекта. Если бы TS решила реализовать их в будущем, описанная выше техника может нарушиться.

  • 9
    Для ясности, приведенный выше ответ по-прежнему работает с TS 2.3. Однако, если вы используете «const enum», а не просто «enum», только тогда это не сработает. Использование const enum в основном говорит TS о необходимости поиска и замены; каждое место, где вы используете MyEnum.Foo, будет заменено соответствующим числовым значением.
152

Хотя ответ уже предоставлен, почти никто не указал на документы

Вот фрагмент

enum Enum {
    A
}
let nameOfA = Enum[Enum.A]; // "A"
  • 10
    Там также говорится: «Имейте в виду, что члены перечисления строк вообще не генерируют обратное отображение».
  • 0
    Спасибо, я сделал это один раз и не мог вспомнить. Правильный ответ
Показать ещё 1 комментарий
102

Ого. Это закончилось тем, что стало проще, чем я думал, и это не имеет никакого отношения ко мне, что бы то ни было.

enum myEnum { entry1, entry2 }
console.log(myEnum[myEnum.entry1]); // Will output "entry1" to the console.
47

Предполагая, что вы придерживаетесь правил и только производите перечисления с числовыми значениями, вы можете использовать этот код. Это правильно обрабатывает случай, когда у вас есть имя, совпадающее с допустимым числом

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']
  • 0
    Предупреждение В современном машинописном тексте (tsc 2.5.2 atm) вам даже не разрешено иметь цифровую строку в качестве ключа для начала. Как таковой ответ Химанго лучше, так как он охватывает все случаи и не имеет недостатков.
35

Для меня более простой, практичный и прямой способ понять, что происходит, заключается в следующем перечислении:

enum colors { red, green, blue };

Будет преобразован по существу в это:

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

Из-за этого будет выполнено следующее:

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

Это создает простой способ получить имя перечисления следующим образом:

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

Он также создает хороший способ преобразования строки в нумерованное значение.

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

Две ситуации выше - гораздо более распространенная ситуация, потому что обычно вас гораздо больше интересует имя определенного значения и сериализует значения в общем виде.

25

Если вы только ищите имена и итерации позже, используйте:

Object.keys(myEnum).map(key => myEnum[key]).filter(value => typeof value === 'string') as string[];
  • 7
    Или с помощью ES2017 lib: Object.values(myEnum).filter(value => typeof value === 'string') as string[];
19

С текущим TypeScript Версия 1.8.9 я использую типизированные перечисления:

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

с результатами в этом объекте Javascript:

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

поэтому я должен запрашивать ключи и значения и возвращать только значения:

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]]);
        }
    }
}

И я получаю ключи опций в массиве:

optionNames = [ "OPTION1", "OPTION2" ];
  • 1
    <любой> сделал свое дело! Спасибо.
9

Это решение тоже работает.

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

var type: ScreenType = ScreenType.Edit;

console.log(ScreenType[type]); //Edit
  • 1
    Самый простой ответ, безусловно , спасибо.
9

Вы можете использовать пакет enum-values который я написал, когда у меня была такая же проблема:

Git: enum-значения

var names = EnumValues.getNames(myEnum);
  • 2
    Вы на самом деле не отвечаете на вопрос, было бы лучше задокументировать ваш ответ с помощью кода / и т. Д., Но я нашел пакет полезным.
5

Начиная с Typescript 2.4, перечисления могут содержать инициализаторы строк https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html.

Это позволяет вам написать:

 enum Order {
      ONE = "First",
      TWO = "Second"
 }

console.log('One is ${Order.ONE.toString()}');

и получить этот вывод:

Один первый

5

Пусть ts-enum-util (github, npm) сделает всю работу за вас и предоставит множество дополнительных типобезопасных утилит. Работает как со строковыми, так и с числовыми перечислениями, должным образом игнорируя записи обратного просмотра числового индекса для числовых перечислений:

Строковое перечисление:

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();

Числовое перечисление:

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();
5

Начиная с машинописного текста 2.4, перечисление больше не будет содержать ключ в качестве члена. источник из Tymescript readme

Предостережение заключается в том, что инициализированные строкой перечисления не могут быть преобразованы в обратный путь для получения исходного имени члена перечисления. Другими словами, вы не можете написать Colors ["RED"], чтобы получить строку "Red".

Мое решение:

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

Основываясь на некоторых ответах выше, я придумал эту сигнатуру безопасной для типов функции:

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

Использование:

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

тип stringVals является 'entry1' | 'entry2' 'entry1' | 'entry2'

(myEnum: T): keyof T { return Object.keys(myEnum).filter(k => typeof (myEnum as any)[k] === 'number') as any; } enum myEnum { entry1, entry2 }; const stringVals = getStringValuesFromEnum(myEnum); rel="nofollow noreferrer">Увидеть это в действии

  • 1
    Функция должна возвращать (keyof T)[] вместо keyof T Кроме того, export останавливает вашу игровую площадку от работы.
  • 0
    Кроме этого, это выглядит как лучшее решение, которое я видел.
2

Согласно документации по машинописи, мы можем сделать это через Enum со статическими функциями.

Получить Enum Name со статическими функциями

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 

чтобы узнать больше о Enum со статической функцией, перейдите по ссылке ниже https://basarat.gitbooks.io/typescript/docs/enums.html

1

Я думаю, что лучший способ - просто объявить желаемые значения перечисления. Таким образом, доступ к ним чистый и красивый (каждый раз).

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

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

будет производить:

VALUE1
VALUE2
1

Я нахожу это решение более элегантным:

for (let val in myEnum ) {

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

Отображается:

bar 
foo
0

Я написал класс EnumUtil, который выполняет проверку типа по значению enum:

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

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

Как это использовать:

enum TestEnum{
  A= 0,
  B= 1
}

EnumUtils.getEnumKeys(TestEnum, "number");
EnumUtils.getEnumValues(TestEnum, "number");

Результат для ключей: ["A", "B"]

Результат для значений: [0, 1]

0

Единственное решение, которое работает для меня во всех случаях (даже если значения являются строками), заключается в следующем:

var enumToString = function(enumType, enumValue) {
    for (var enumMember in enumType) {
        if (enumType[enumMember]==enumValue) return enumMember
    }
}
-2

Это не совсем ответ на ваш вопрос, но это хитрость для решения вашей проблемы.

export module Gender {

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

  export const List = [
    { Female: Type.Female },
    { Male: Type.Male }
  ];

}

Вы можете расширить свою модель списка так, как вы хотите.

export const List = [
    { Female: { key: 'Female', value: Type.Female } },
    { Male: { key: 'Male', value: Type.Male } }
  ]

Теперь вы можете использовать его следующим образом:

for(let gender of Gender.List){
  console.log(gender.Female.key);
  console.log(gender.Female.value);
}

или же:

if(i === Gender.Type.Male){
  console.log("I'm a man.");
}
-2

Мой Enum такой:

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", 
}

таким образом, это возвращение не определено:

UserSorting[UserSorting.SortByUpdatedAt]

Чтобы решить эту проблему, я выбрал другой способ сделать это с помощью Pipe:

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;
    }
}

И использовать это:

return this.enumKeyPipe.transform(UserSorting, [UserSorting.SortByUpdatedAt]);
  • 0
    даже с -1 мое решение работает правильно :)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню