如何获取枚举条目的名称?


314

我想迭代一个TypeScript enum类型并获取每个枚举的符号名称,例如:

enum myEnum { entry1, entry2 }

for (var entry in myEnum) { 
    // use entry's name here, e.g., "entry1"
}

这个微小的枚举包具有getAllEnumValuesgetAllEnumKeys满足您的目的
Transang

Answers:


255

您发布的代码可以使用;它将打印出该枚举的所有成员,包括枚举成员的值。例如,以下代码:

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

那只会打印出名称:

枚举成员:bar

枚举成员:foo

警告:这稍微依赖于实现细节:TypeScript将枚举编译为JS对象,而枚举值是该对象的成员。如果TS决定将来以不同的方式实现它们,则上述技术可能会失效。


23
需要明确的是,以上答案从TS 2.3开始仍然有效。但是,如果使用“ const枚举”而不是“枚举”,则只有这样才能使用。使用const枚举基本上是告诉TS进行搜索和替换;您在每个使用MyEnum.Foo的地方,都会将其替换为相应的数值。
Judah Gabriel Himango'5

我认为+enumMember >= 0应该是isFinite(+enumMember)因为负值或浮点值也被反向映射。(游乐场
spenceryue

341

尽管已经提供了答案,但几乎没有人指出文档

这是一个片段

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

请记住,字符串枚举成员根本不会生成反向映射。


38
它还说:“请记住,字符串枚举成员根本不会生成反向映射。”
jbojcic

1
显示01从这个枚举怎么样?export enum Octave { ZERO = 0, ONE = 1 }
Stephane

@jbojcic与情况有关enum Enum {"A"}; let nameOfA = Enum[Enum.A];吗?从
typescript@2.9.2开始,它对

如何遍历值?
shioko

55

假设您遵守规则,并且只生成带有数值的枚举,则可以使用此代码。这可以正确处理您的名称恰巧是有效数字的情况

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']

警告在现代打字稿(tsc 2.5.2 atm)中,甚至不允许使用数字字符串作为键开头。这样一来,Himango的答案就更好了,因为它涵盖了所有情况并且没有缺点。
srcspider

52

对我来说,一种更简单,实用,直接的方式来了解发生了什么事情,它是以下列举:

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

上面的两种情况是更常见的情况,因为通常您对特定值的名称和以通用方式序列化值更感兴趣。


49

如果仅搜索名称并在以后进行迭代,请使用:

Object.keys(myEnum).map(key => myEnum[key]).filter(value => typeof value === 'string') as string[];

13
或使用ES2017库:Object.values(myEnum).filter(value => typeof value === 'string') as string[];

我需要创建一个字典,然后以您的回答为起点。如果有人需要它,Object.values(myEnum).filter(value => typeof value === 'string').map(key => { return {id: myEnum[key], type: key }; });
Fejs

25

在当前的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" ];


17

此解决方案也可以。

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

var type: ScreenType = ScreenType.Edit;

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

14

在这里找到的另一个有趣的解决方案是使用ES6 Map:

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

采用

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

10

ts-enum-utilgithubnpm)为您完成工作,并提供许多其他类型安全的实用程序。同时适用于字符串枚举和数字枚举,正确忽略数字枚举的数字索引反向查找条目:

字符串枚举:

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

9

从TypeScript 2.4开始,枚举将不再包含该密钥作为成员。来自TypeScript自述文件

需要注意的是,不能对通过字符串初始化的枚举进行反向映射以获取原始枚举成员名称。换句话说,您不能编写Colors [“ RED”]来获取字符串“ Red”。

我的解决方案:

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

8

您可以使用在enum-values遇到相同问题时编写的软件包:

Git:枚举值

var names = EnumValues.getNames(myEnum);

3
您并不是真的要回答这个问题,最好用代码/ etc记录您的回答,但我确实发现该软件包很有用。
lucuma

7

基于上面的一些答案,我想到了这种类型安全的函数签名:

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'

实际观看


1
该函数应返回(keyof T)[]而不是keyof T。此外,还可以export阻止您的游乐场工作。
乔尔德

7

似乎所有答案都无法在strict-mode下使用字符串枚举。

将枚举视为:

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

使用进行访问AnimalEnum["dog"]可能会导致类似以下的错误:

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

对于这种情况的正确解决方案,将其写为:

AnimalEnum["dog" as keyof typeof AnimalEnum]

keyof与with配合使用的出色解决方案typeof!其他解决方案似乎不太透明,但毕竟我认为Typescript需要在DX上不断改进-Enum的开发人员经验
Shaung Cheng

5

我认为最好的方法是只声明所需的枚举值。这样访问它们既干净又漂亮(每次)。

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

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

将产生:

VALUE1
VALUE2

5

根据TypeScript文档,我们可以使用带有静态函数的Enum进行此操作。

使用静态函数获取枚举名称

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


4

适用于我的所有情况(即使值是字符串)的唯一解决方案如下:

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

4

老问题了,但是,为什么不使用const对象图呢?

而不是这样做:

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]

执行此操作(请注意as const演员表):

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]

如果我错了,请纠正我,但console.log(Object.keys(Foo))在第一个示例中只会返回["BAR", "EVERYTHING_IS_TERRIBLE"]..
彼得

@Peter 在ts游乐场看一眼,只需打开控制台并单击run。至少对我来说,它打印["60", "80", "BAR", "EVERYTHING_IS_TERRIBLE"]
加布里埃尔·德·奥利维拉·罗登

1
看来您的权利,有趣的事情,如果你从数字更改为字符串你得到的输出我所料,我不知道为什么打字稿把手字符串和数字在不同枚举..
彼得

4

我通过搜索“ TypeScript遍历枚举键”发现了这个问题。所以我只想发布对我而言适用的解决方案。也许对某人也会有所帮助。

我的情况如下:我想遍历每个枚举键,然后过滤一些键,然后访问一些具有键的对象,这些键作为来自枚举的计算值。所以这就是我这样做的方法,没有任何TS错误。

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

3

我写了一个EnumUtil类,它通过枚举值进行类型检查:

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

如何使用它:

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

NumberValueEnum键的结果:[“ A”,“ B”]

NumberValueEnum值的结果:[0,1]

StringValueEnumkeys的结果:[“ A”,“ B”]

StringValueEnumvalues的结果:[“ A”,“ B”]



2

我的枚举是这样的:

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

所以这样做返回undefined

UserSorting[UserSorting.SortByUpdatedAt]

要解决此问题,我选择了另一种使用管道的方法:

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

2

如果您有枚举

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

然后,您可以获取键和值,例如:

Object.keys(Diet).forEach((d: Diet) => {
  console.log(d); // KETO
  console.log(Diet[d]) // Ketogenic
});

这将导致错误: 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)
jrheling

1

我编写了一个辅助函数来枚举枚举:

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

用法:

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

该函数返回可以轻松枚举的内容,并且还强制转换为枚举类型。


0

使用当前版本的TypeScript,您可以使用诸如此类的函数将Enum映射到您选择的记录。请注意,您无法使用这些函数定义字符串值,因为它们会查找具有数字值的键。

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

0

这里已经有很多答案,但是我想我还是会将解决方案扔到堆栈上。

TypeScript游乐场

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

为清晰起见:

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

TypeScript记录参考

一个很好的辅助函数:

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

// getAccountTypeName(AccountType.Twitter) === 'Twitter'

0

要获取枚举值列表,您必须使用:

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

Object.values(AnimalEnum);

-1

这不是您问题的确切答案,但这是解决您的问题的技巧。

export module Gender {

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

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

}

您可以按照自己的方式扩展列表模型。

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

现在,您可以通过以下方式使用它:

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

要么:

if(i === Gender.Type.Male){
  console.log("I am a man.");
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.