如何获取typescript枚举项的名称?

How does one get the names of TypeScript enum entries?

我想知道如何迭代typescript枚举和每个枚举的符号名。

例如。,

1
2
3
4
5
enum myEnum { entry1, entry2 }

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

虽然已经提供了答案,但几乎没有人指向文档

这是一个片段

1
2
3
4
enum Enum {
    A
}
let nameOfA = Enum[Enum.A]; //"A"


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

1
2
3
4
5
enum myEnum { bar, foo }

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

将打印以下内容:

1
2
3
4
Enum member: 0
Enum member: 1
Enum member: bar
Enum member: foo

如果只需要成员名而不需要值,可以这样做:

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

只打印出名字:

Enum member: bar

Enum member: foo

警告:这稍微依赖于实现细节:typescript将枚举编译为JS对象,枚举值是该对象的成员。如果TS决定在将来不同地实现它们,那么上述技术可能会失败。


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

1
2
3
4
5
6
7
8
9
10
11
12
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']


对我来说,了解正在发生的事情的一个简单、实用和直接的方法是以下列举:

1
enum colors { red, green, blue };

将基本上转换为:

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

因此,以下内容是正确的:

1
2
3
colors.red === 0
colors[colors.red] ==="red"
colors["red"] === 0

这将创建一种简单的方法来获取枚举的名称,如下所示:

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

它还创建了一种将字符串转换为枚举值的好方法。

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

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


如果只搜索名称并稍后迭代,请使用:

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


对于当前的TypeScript版本1.8.9,我使用类型化枚举:

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

在这个javascript对象中得到结果:

1
2
3
4
5
6
Option = {
   "OPTION1":"this is option 1",
   "OPTION2":"this is option 2",
   "this is option 1":"OPTION1",
   "this is option 2":"OPTION2"
}

所以我必须通过键和值进行查询,并且只返回值:

1
2
3
4
5
6
7
8
9
10
11
12
let optionNames: Array = [];    
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]]);
        }
    }
}

我在一个数组中接收选项键:

1
optionNames = ["OPTION1","OPTION2" ];


从typescript 2.4开始,枚举可以包含字符串初始化器https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html

这允许您写:

1
2
3
4
5
6
 enum Order {
      ONE ="First",
      TWO ="Second"
 }

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

得到这个输出:

One is First


这个解决方案也有效。

1
2
3
4
5
6
7
8
9
enum ScreenType {
    Edit = 1,
    New = 2,
    View = 4
}

var type: ScreenType = ScreenType.Edit;

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


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

git:枚举值

1
var names = EnumValues.getNames(myEnum);


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

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

用途:

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

stringVals型为'entry1' | 'entry2'型。

行动起来看看


让EDOCX1(Github,NPM)为您完成这项工作,并提供许多额外的类型安全实用程序。同时使用字符串和数字枚举,正确忽略数字枚举的数字索引反向查找条目:

字符串枚举:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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();

数值枚举:

1
2
3
4
5
6
7
8
9
10
11
12
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();

从typescript 2.4开始,枚举将不再包含作为成员的键。来自typescript自述文件的源文件

The caveat is that string-initialized enums can't be reverse-mapped to get the original enum member name. In other words, you can't write Colors["RED"] to get the string"Red".

我的解决方案:

1
2
3
4
5
6
7
8
9
10
export const getColourKey = (value: string ) => {
    let colourKey = '';
    for (const key in ColourEnum) {
        if (value === ColourEnum[key]) {
            colourKey = key;
            break;
        }
    }
    return colourKey;
};

另一个有趣的解决方案是使用ES6地图:

1
2
3
4
5
6
7
8
9
10
11
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']
]);

使用

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

根据typescript文档,我们可以通过使用静态函数的枚举来实现这一点。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

要了解有关使用静态函数的枚举的更多信息,请执行以下链接https://basarat.gitbooks.io/typescript/docs/enums.html


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

1
2
3
4
5
enum myEnum { entry1 = 'VALUE1', entry2 = 'VALUE2' }

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

将产生:

1
2
VALUE1
VALUE2

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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);
  }
}

如何使用它:

1
2
3
4
5
6
7
enum TestEnum{
  A= 0,
  B= 1
}

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

键的结果:["A","B"]

值的结果:[0,1]


我发现这个解决方案更优雅:

1
2
3
4
5
for (let val in myEnum ) {

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

它显示:

1
2
bar
foo

我通过搜索"typescript迭代枚举键"找到了这个问题。所以我只想在我的案例中发布适合我的解决方案。也许它也会对某人有所帮助。

我的例子如下:我想迭代每个枚举键,然后过滤一些键,然后访问一些具有键作为枚举计算值的对象。所以我就是这样做的,没有任何TS错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    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 !== InsuranceType.OSAGO
    )

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

我的枚举如下:

1
2
3
4
5
6
7
8
9
10
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",
}

因此,此返回未定义:

1
UserSorting[UserSorting.SortByUpdatedAt]

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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;
    }
}

并使用它:

1
return this.enumKeyPipe.transform(UserSorting, [UserSorting.SortByUpdatedAt]);


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

1
2
3
4
5
var enumToString = function(enumType, enumValue) {
    for (var enumMember in enumType) {
        if (enumType[enumMember]==enumValue) return enumMember
    }
}

这不完全是你问题的答案,但它是解决你问题的一个技巧。

1
2
3
4
5
6
7
8
9
10
11
12
13
export module Gender {

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

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

}

您可以根据需要扩展列表模型。

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

现在,您可以这样使用它:

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

或:

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