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 |
您可以使用我在遇到相同问题时编写的
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); |
行动起来看看
让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."); } |