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

680

我想迭代 TypeScript 枚举对象并获取每个枚举值的名称,例如: enum myEnum { entry1, entry2 }

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

1
这个小巧的enum-for包拥有getAllEnumValuesgetAllEnumKeys函数,供您使用。 - transang
2
我已经创建了一个PR(问题)来为TypeScript添加对for (const [name, value] of MyEnum) {的本地支持。希望有一天这将变得更加容易!(PR链接:https://github.com/microsoft/TypeScript/pull/42465,问题链接:https://github.com/microsoft/TypeScript/issues/42457) - Timmmm
一定很困难才提供不了 EnumType.name() 方法。 - html_programmer
1
我发现这篇文章很有用 https://www.technicalfeeder.com/2021/07/mastering-enum-in-typescript/ - Etienne
43个回答

822

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

这是一小段代码

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

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

3
从这个枚举中显示01怎么样? export enum Octave { ZERO = 0, ONE = 1 } - Stephane
3
如何遍历数值? - shioko
4
在 JavaScript 中,枚举是一个以 [value]: name 形式存储的对象。你可以通过 Object.keys(enum) 获取所有值、Object.values(enum) 获取所有名称,或使用 for(const [value, name] of Object.entries(enum)) { ... } 一次性进行迭代。需要注意的是,当你获取枚举的值时,它们将会是字符串,而不是像你期望的那样是数字(因为在 JavaScript 中,对象的键总是字符串)。 - user0103
4
我不认为这个回答解决了所问的问题。是的,这里陈述的事实是正确的,人们可以从中推断出一个答案,但并没有直接的回答。 - fgblomqvist
2
如果您将枚举命名为除Enum以外的其他名称,会更加清晰易懂。 - Hoppe
显示剩余3条评论

377

你发布的代码是有效的;它将打印出枚举的所有成员,包括枚举成员的值。例如,以下代码:

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 = Number(enumMember) >= 0
   if (isValueProperty) {
      console.log("enum member: ", myEnum[enumMember]);
   }
}

那将仅打印出名称:

Enum member: bar  
Enum member: foo

注意:这在某种程度上依赖于一些实现细节:TypeScript将枚举编译为一个带有枚举值作为对象成员的JS对象。如果TS决定在未来以不同的方式实现它们,上述技巧可能会失效。


40
要明确的是,上面的答案在TS 2.3仍然适用。但是,如果您使用"const enum"而不是只使用"enum",那么它就不起作用了。使用const enum基本上是告诉TS进行搜索和替换;每次您使用MyEnum.Foo时,它都会被替换为相应的数字值。 - Judah Gabriel Himango
1
我认为 +enumMember >= 0 应该改为 isFinite(+enumMember),因为负数或浮点数值也会被反向映射。(Playground) - spenceryue
1
枚举条目可以是带有前导零的字符串,例如00111,您也需要将其排除在外。 - Austaras
从TS 4开始,不支持数字和异构枚举。 - polkovnikov.ph

133

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

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];
上述两种情况更为常见,因为通常您对特定值的名称以及以通用方式序列化值更感兴趣。

1
这是关于TS枚举如何工作的好描述,但并没有回答如何“迭代”每个枚举符号名称的问题。 - polkovnikov.ph
迄今为止最好的枚举工作示例!谢谢。 - VPetrovic

104
如果您仅搜索名称并稍后进行迭代,请使用以下内容:
Object.keys(myEnum).map(key => myEnum[key]).filter(value => typeof value === 'string') as string[];

32
可以使用 ES2017 库:Object.values(myEnum).filter(value => typeof value === 'string') as string[];来实现。该代码将枚举对象 myEnum 中所有值类型为字符串的值筛选出来,并转换成一个字符串数组。 - None
3
或者只需使用 Object.values(myEnum).filter(isNaN) 作为字符串数组。 - ihor.eth
2
Object.keys(myEnum) 不就足以获取枚举对象中键名的数组吗? - Bruno Negrão Zica
对于 enum Test1 { A = "C", B = "D"} 返回 ["C", "D"]。这是值,而不是键。 - polkovnikov.ph
@BrunoNegrãoZica Object.keys(myEnum) 不仅会返回枚举的字符串键,还会返回它们在枚举中对应的索引。 例如enum Color { Black, White } console.log(Object.keys(Color)) // '0', '1', 'Black', 'White' - Adilet Soronov
显示剩余2条评论

64

假设您遵循规则并仅生成具有数字值的枚举,您可以使用此代码。这段代码可以正确处理名称巧合为有效数字的情况。

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

警告:在现代 TypeScript(目前为 tsc 2.5.2)中,您甚至不允许将数字字符串作为键。因此,Himango 的答案更好,因为它涵盖了所有情况并且没有缺点。 - srcspider
Object.prototype.foo = 1; - polkovnikov.ph

49

看起来这里的答案都不能在 strict 模式下使用字符串枚举。

考虑以下枚举:

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]

使用 keyoftypeof 的绝妙解决方案!其他解决方案似乎相当晦涩,但毕竟我认为Typescript需要在枚举的开发者体验上不断改进。 - Shawn
16
当值和键不相同时,情况就不太好了。 - Denny
当您想要在传递键时映射枚举值时,此解决方案非常好。 - kapil
这个解决方案非常简洁,但完美地满足了我的需求。做得非常好!我在API响应的映射函数中使用了它。比迭代对象值或键并从那里回溯要简单得多。非常感谢! - BondAddict
这就是我一直在寻找的,谢谢! - undefined

33

2
它如何“迭代”每个枚举符号名称?这根本不是对所提出问题的答案。 - polkovnikov.ph

32

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

好的,代码说的是不同的事情,你会得到:optionNames = [["OPTION1", "这是选项1"], ["OPTION2", "这是选项2"]],但总体上我欣赏你删除双重反向条目的想法,其他人都认为值始终是一个数字。 - Dima Karaush
@DimaKaraush 并不是所有人都这样认为。此外,这个答案依赖于对象键的顺序,是明显错误的。 - polkovnikov.ph
修复代码问题后,它生成[["OPTION1", "this is option 1"], ["OPTION2", "this is option 2"]]。即使取这些元组的第一个元素,它在枚举Test2 { A,B }上产生错误,生成了["0", "1", "A", "B"] - polkovnikov.ph

30

这个解决方案也可行。

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

var type: ScreenType = ScreenType.Edit;

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

2
为什么它对我打印出“未定义”?有任何想法吗? - itsji10dra
1
它如何“迭代”每个枚举符号名称?这根本不是对所提出问题的回答。 - polkovnikov.ph
当您展示如何使用枚举的数组访问器进行访问时,我建议添加迭代部分以回答该问题。 - DerStoffel

27

简而言之

如果你的 enums 如下所示:

export enum Colors1 {
  Red = 1,
  Green = 2,
  Blue = 3
}

获取特定文本和值:

console.log(Colors1.Red); // 1 
console.log(Colors1[Colors1.Red]); // Red

获取值和文本的列表:

public getTextAndValues(e: { [s: number]: string }) {
  for (const enumMember in e) {
    if (parseInt(enumMember, 10) >= 0) {
      console.log(e[enumMember]) // Value, such as 1,2,3
      console.log(parseInt(enumMember, 10)) // Text, such as Red,Green,Blue
    }
  }
}
this.getTextAndValues(Colors1)

如果你的enums如下:

export enum Colors2 {
  Red = "Red",
  Green = "Green",
  Blue = "Blue"
}

获取特定的文本和值:

console.log(Colors2.Red); // Red
console.log(Colors2["Red"]); // Red

获取值和文本列表:

public getTextAndValues(e: { [s: string]: string }) {
  for (const enumMember in e) {
    console.log(e[enumMember]);// Value, such as Red,Green,Blue
    console.log(enumMember); //  Text, such as Red,Green,Blue
  }
}
this.getTextAndValues(Colors2)

4
无法处理字符串和异构枚举类型。从"thsi"的样子来看,很容易推断出代码从未被编译过。 - polkovnikov.ph
@polkovnikov.ph- 我更新了我的回答,我认为你不应该因为写错而对一个问题进行贬值。 - Abolfazl Roshanzamir
2
我给它投了反对票,因为它是错误的。数字枚举不是唯一的枚举类型。而且我不明白为什么数字必须是非负的。enum A { B = -1 } 是完全有效的。 - polkovnikov.ph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接