我想迭代一个 TypeScript 枚举对象并获取每个枚举的符号名称,例如: enum myEnum { entry1, entry2 }
for (var entry in myEnum) {
// use entry's name here, e.g., "entry1"
}
EnumType.name()
方法一定很难。
虽然已经给出了答案,但几乎没有人指出docs
这是一个片段
enum Enum {
A
}
let nameOfA = Enum[Enum.A]; // "A"
请记住,字符串枚举成员根本不会生成反向映射。
您发布的代码将起作用;它将打印出枚举的所有成员,包括枚举成员的值。例如,下面的代码:
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 决定在未来以不同的方式实现它们,上述技术可能会失效。
00111
,您也需要排除这些条目
对我来说,了解正在发生的事情的一种更简单、实用和直接的方法是以下枚举:
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];
上述两种情况是更为常见的情况,因为通常您对特定值的名称和以通用方式序列化值更感兴趣。
如果您只搜索名称并稍后进行迭代,请使用:
Object.keys(myEnum).map(key => myEnum[key]).filter(value => typeof value === 'string') as string[];
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 }; });
Object.keys(myEnum)
不足以在枚举对象中获取包含键名的数组吗?
Object.entries(temp1).splice(Object.keys(temp1).length/2)
所以我们得到了条目
假设您遵守规则并且只生成带有数值的枚举,您可以使用此代码。这可以正确处理您的姓名恰好是有效数字的情况
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 版本 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", "this is option 1"], ["OPTION2", "this is option 2"]]
,但总的来说,我很欣赏你删除双重反向条目的想法,这里的其他人都认为值总是一个数字
从 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()}`);
并得到这个输出:
一个是第一
似乎这里的所有答案都不适用于 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]
keyof
与 typeof
一起使用的绝妙解决方案!其他解决方案似乎很不透明,但毕竟我认为 Typescript 需要不断改进 DX - Enum 的开发人员体验
该解决方案也有效。
enum ScreenType {
Edit = 1,
New = 2,
View = 4
}
var type: ScreenType = ScreenType.Edit;
console.log(ScreenType[type]); //Edit
简而言之
如果您的 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)
thsi
的外观,很容易暗示代码从未编译过。
enum A { B = -1 }
完全有效。
让 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();
"0"
和 0
。此外,图书馆的大小是荒谬的。
"0"
和 0
的示例?还有关于库的大小,你只是看 NPM 包的总大小吗?原始代码本身的大小非常小。大部分包大小是文档(代码注释和降价文件),并且完整记录的源代码包含在源映射中以进行调试。
另一个有趣的解决方案 found here 是使用 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
我厌倦了浏览错误的答案,我自己做了。
这个有测试。
适用于所有类型的枚举。
输入正确。
type EnumKeys<Enum> = Exclude<keyof Enum, number>
const enumObject = <Enum extends Record<string, number | string>>(e: Enum) => {
const copy = {...e} as { [K in EnumKeys<Enum>]: Enum[K] };
Object.values(e).forEach(value => typeof value === 'number' && delete copy[value]);
return copy;
};
const enumKeys = <Enum extends Record<string, number | string>>(e: Enum) => {
return Object.keys(enumObject(e)) as EnumKeys<Enum>[];
};
const enumValues = <Enum extends Record<string, number | string>>(e: Enum) => {
return [...new Set(Object.values(enumObject(e)))] as Enum[EnumKeys<Enum>][];
};
enum Test1 { A = "C", B = "D"}
enum Test2 { A, B }
enum Test3 { A = 0, B = "C" }
enum Test4 { A = "0", B = "C" }
enum Test5 { undefined = "A" }
enum Test6 { A = "undefined" }
enum Test7 { A, B = "A" }
enum Test8 { A = "A", B = "A" }
enum Test9 { A = "B", B = "A" }
console.log(enumObject(Test1)); // {A: "C", B: "D"}
console.log(enumObject(Test2)); // {A: 0, B: 1}
console.log(enumObject(Test3)); // {A: 0, B: "C"}
console.log(enumObject(Test4)); // {A: "0", B: "C"}
console.log(enumObject(Test5)); // {undefined: "A"}
console.log(enumObject(Test6)); // {A: "undefined"}
console.log(enumObject(Test7)); // {A: 0,B: "A"}
console.log(enumObject(Test8)); // {A: "A", B: "A"}
console.log(enumObject(Test9)); // {A: "B", B: "A"}
console.log(enumKeys(Test1)); // ["A", "B"]
console.log(enumKeys(Test2)); // ["A", "B"]
console.log(enumKeys(Test3)); // ["A", "B"]
console.log(enumKeys(Test4)); // ["A", "B"]
console.log(enumKeys(Test5)); // ["undefined"]
console.log(enumKeys(Test6)); // ["A"]
console.log(enumKeys(Test7)); // ["A", "B"]
console.log(enumKeys(Test8)); // ["A", "B"]
console.log(enumKeys(Test9)); // ["A", "B"]
console.log(enumValues(Test1)); // ["C", "D"]
console.log(enumValues(Test2)); // [0, 1]
console.log(enumValues(Test3)); // [0, "C"]
console.log(enumValues(Test4)); // ["0", "C"]
console.log(enumValues(Test5)); // ["A"]
console.log(enumValues(Test6)); // ["undefined"]
console.log(enumValues(Test7)); // [0, "A"]
console.log(enumValues(Test8)); // ["A"]
console.log(enumValues(Test9)); // ["B", "A"]
假设您有一个 enum
export enum SCROLL_LABEL_OFFSET {
SMALL = 48,
REGULAR = 60,
LARGE = 112
}
并且您想创建一个基于枚举的类型,而不仅仅是复制和粘贴。您可以使用 enum
创建您的 type
,如下所示:
export type ScrollLabelOffset = keyof typeof SCROLL_LABEL_OFFSET;
结果,您将收到一个可能值为 'SMALL' | 'REGULAR' | 'LARGE'
的 type
从 TypeScript 2.4 开始,枚举不再包含作为成员的键。 source from TypeScript 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;
};
在 TypeScript 中,枚举被编译为 javascript 中的映射(从键中获取值):
enum MyEnum {
entry0,
entry1,
}
console.log(MyEnum['entry0']); // 0
console.log(MyEnum['entry1']); // 1
它还创建了一个反向映射(从值中获取键):
console.log(MyEnum[0]); // 'entry0'
console.log(MyEnum[0]); // 'entry1'
因此,您可以通过执行以下操作访问条目的名称:
console.log(MyEnum[MyEnum.entry0]); // 'entry0'
console.log(MyEnum[MyEnum.entry1]); // 'entry1'
但是,字符串枚举在设计上没有反向映射(请参阅 comment 和 pull request),因为这可能会导致映射对象中的键和值之间发生冲突。
enum MyEnum {
entry0 = 'value0',
entry1 = 'value1',
}
console.log(MyEnum['value0']); // undefined
console.log(MyEnum['value1']); // undefined
如果你想强制你的字符串枚举编译一个反向映射(然后你必须确保所有的键和值都不同),你可以使用这个技巧:
enum MyEnum {
entry0 = <any>'value0',
entry1 = <any>'value1',
}
console.log(MyEnum['value0']); // 'entry0'
console.log(MyEnum['value1']); // 'entry1'
console.log(MyEnum[MyEnum.entry0]); // 'entry0'
console.log(MyEnum[MyEnum.entry1]); // 'entry1'
基于上面的一些答案,我想出了这个类型安全的函数签名:
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'
(keyof T)[]
而不是 keyof T
。此外,export
会阻止您的 Playground 工作。
您可以使用我遇到相同问题时编写的 enum-values
包:
var names = EnumValues.getNames(myEnum);
Object.keys(e).filter(key => isNaN(+key))
,它不适用于字符串枚举等,对吧?
在所有情况下(即使值是字符串)都适用于我的唯一解决方案如下:
var enumToString = function(enumType, enumValue) {
for (var enumMember in enumType) {
if (enumType[enumMember]==enumValue) return enumMember
}
}
根据 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
我写了一个 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"]
他们在官方文档中提供了一个称为“反向映射”的概念。它帮助了我:
https://www.typescriptlang.org/docs/handbook/enums.html#reverse-mappings
解决方案非常简单:
enum Enum {
A,
}
let a = Enum.A;
let nameOfA = Enum[a]; // "A"
enum
上。
我通过搜索“TypeScript iterate over enum keys”找到了这个问题。所以我只想发布适合我的解决方案。也许它也会对某人有所帮助。
我的情况如下:我想遍历每个枚举键,然后过滤一些键,然后访问一些对象,该对象将键作为枚举的计算值。所以这就是我在没有任何 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]
}))
老问题,但是,为什么不使用 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"]
..
["60", "80", "BAR", "EVERYTHING_IS_TERRIBLE"]
如果你有枚举
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)
您可以通过这种方式从 Enum 中获取名称数组:
const enumNames: string[] = Object.keys(YourEnum).filter(key => isNaN(Number(key)));
有数字枚举:
enum MyNumericEnum {
First = 1,
Second = 2
}
您需要先将其转换为数组:
const values = Object.values(MyNumericEnum);
// ['First', 'Second', 1, 2]
如您所见,它包含键和值。钥匙先走。
之后,您可以检索其密钥:
values.slice(0, values.length / 2);
// ['First', 'Second']
和价值观:
values.slice(values.length / 2);
// [1, 2]
对于字符串枚举,您可以使用 Object.keys(MyStringEnum)
来获取键和 Object.values(MyStringEnum)
来分别获取值。
尽管提取混合枚举的键和值有些挑战。
我发现该解决方案更优雅:
for (let val in myEnum ) {
if ( isNaN( parseInt( val )) )
console.log( val );
}
它显示:
bar
foo
可以很简短:
enum AnimalEnum {
DOG = "dog",
CAT = "cat",
MOUSE = "mouse"
}
Object.keys(AnimalEnum).filter(v => typeof v == 'string' && isNaN(v))
我的枚举是这样的:
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]
为了解决这个问题,我选择了另一种使用管道的方法:
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
怎么样?export enum Octave { ZERO = 0, ONE = 1 }
enum Enum {"A"}; let nameOfA = Enum[Enum.A];
?从 typescript@2.9.2 开始,它对我来说效果很好......[value]: name
的一个对象,因此您可以获取像Object.keys(enum)
这样的所有值、所有名称Object.values(enum)
并使用for(const [value, name] of Object.entries(enum)) { ... }
一次性迭代。请注意,当您获取值时,它们将是字符串,而不是您期望的数字(因为在 JS 中对象的键是字符串)。