我在TypeScript中定义了以下enum:

enum Color{
    Red, Green
}

现在在我的函数中,我以字符串的形式接收颜色。我尝试了以下代码:

var green= "Green";
var color : Color = <Color>green; // Error: can't convert string to enum

如何将该值转换为enum?


当前回答

TL;博士: :

创建一个函数,解析字符串值并将其转换为枚举。 如果你需要给定值的键名,不要使用TS enum。

首先,枚举是人类可读的名称和值之间的映射,这就是它的用途。

默认值: TS默认情况下会确保枚举中定义的键有唯一的值。

This

enum Color {
    Red, Green
}

等于

enum Color {
    Red = 0,
    Green = 1
}

转译的js代码都将

"use strict";
var Color;
(function (Color) {
    Color[Color["Red"] = 0] = "Red";
    Color[Color["Green"] = 1] = "Green";
})(Color || (Color = {}));

由于这是不可读的,下面是一旦创建的结果对象:

{0: 'Red', 1: 'Green', Red: 0, Green: 1}

该对象具有字符串和数字属性(不可能有任何冲突,因为您不能将枚举键定义为数字)。TS足够酷,可以生成一个包含映射键->值和值->键的对象。

感谢上帝,这是一个双射映射,即每个唯一值都有它的唯一键(因此反过来也是正确的)

现在麻烦来了,如果我强制使用相同的值呢?

enum Color {
    Red = 0,
    Green = 0
}

这是最终创建的js对象

{0: 'Green', Red: 0, Green: 0}

我们不再有双射,(这是满射),没有魔法映射0:['Green', 'Red']。只有0:“绿色”,我们失去了0:“红色”

提示:当值为数字时,TS将总是尝试放置反向映射(value ->键)。

现在,正如你所知道的,你也可以在枚举中定义字符串值,让我们只将Green值更改为"Green"

enum Color {
    Red = 0,
    Green = "GREEN"
}

这是生成的js对象

{0: 'Red', Red: 0, Green: 'GREEN'}

如你所见,Typescript并没有生成映射值->键。 它不会,因为您可能会在值和键名之间发生冲突。记住:键不能是数字,因此当值是数字时,就没有碰撞的风险。

这使您明白,您不应该依赖于枚举的value ->键映射。映射可能根本不存在或不准确。

同样,枚举是(也只能被视为)人类可读的值名称。在某些情况下,ts甚至根本不会产生任何反向映射。这就是定义枚举const时的情况。

const枚举是一个纯编译时的枚举,TS会在编译时将枚举的使用替换为其对应的值

例如:

const enum Color {
    Red = 0,
    Green = "GREEN"
}

被转译为

"use strict";

所以我想说,没什么,因为“use strict”;跟我们写的都没有关系。

下面是一个用法的相同示例:

const enum Color {
    Red = 0,
    Green = "GREEN"
}
console.log(Color.Green);

被转译为

"use strict";
console.log("GREEN" /* Green */);

如你所见,颜色。Green被转译器替换为“Green”。

回到最初的问题,如何将字符串转换为enum ?

解析器解决方案: 我很抱歉,但我推荐的唯一干净的方法是写一个函数,使用开关情况是一个聪明的方法来实现这一点。

function parseColorName(color: string): Color {
  switch (color) {
    case 'Red': return Color.Red;
    case 'Green': return Color.Green;
    default: throw new Error('unknown color');
  }
}

自定义enum解决方案:

请注意,TS枚举是不透明的,这意味着编译器无法正确地键入值。出于这个原因(特别是当你需要使用反向映射时),我建议你自己做枚举,如下所示:

export const ColorType = {
  RED: 'Red',
  GREEN: 'Green',
} as const;

export type ColorType = typeof ColorType[keyof typeof ColorType];

下面是安全的(颜色只能取一个有效的已知值)。简而言之,您依赖于字符串联合而不是枚举值。

const color: ColorType= "Green";
// And if you need to create a color from the enum like value:
const anotherColor: ColorType = ColorType.RED;

其他回答

如果TypeScript编译器知道变量的类型是字符串,那么这是可行的:

let colorName : string = "Green";
let color : Color = Color[colorName];

否则,你应该显式地将其转换为字符串(以避免编译器警告):

let colorName : any = "Green";
let color : Color = Color["" + colorName];

在运行时,两个解决方案都可以工作。

提供的大多数答案都没有对Enums提供广泛的支持。允许OP请求只从字符串值中获取Enum,但是Enum也允许其他值。

interface StandardEnum<T> {
    [id: string]: T | string;
    [nu: number]: string;
}

/**
 * Converts the given representation of the value of one enumerated constant to an equivalent enumerated type.
 *
 * @param type - An enumeration type
 * @param value - A value to convert
 */
export const genericValueToEnum = <T, K extends StandardEnum<T>> (
    type: StandardEnum<T>,
    value: K[keyof K]
): T | undefined => {
    const keys = Object.keys(type); // ...but, not really.
    const values = Object.values(type)
        // Filter enum member names because `Object.values()` includes them.
        .filter((value) => !(
            typeof value === 'string' &&
            keys.includes(value) &&
            type[value] !== value
        ));

    return values.includes(value)
        ? value as unknown as T
        : undefined;
}

这将适用于所有枚举,无论它们多么复杂(或奇怪),只要它们没有被标记。

enum OddEnum {
    None = -1,
    No = 0,
    Yes = 1,
    Twenty = '20'
    Other = 'Other',
    MORE = 'More',
};

genericValueToEnum(OddEnum, -1); // => -1 as OddEnum;
genericValueToEnum(OddEnum, 'Other'); // => 'Other' as OddEnum;
genericValueToEnum(OddEnum, 'MORE'); // => undefined;

Typescript 3.9提案

enum Color{ RED, GREEN }

const color = 'RED' as Color;

容易peasy……柠檬捏的!

试试这个

var color: color =(任何颜色)["绿色];

这对于3.5.3版本来说很好

简单的方法

enum Color { Red, Green }

const c1 = Color["Red"]
const redStr = "Red" // important: use `const`, not mutable `let`
const c2 = Color[redStr]

这既适用于数值枚举,也适用于字符串枚举。不需要使用类型断言。

未知enum字符串

Simple, unsafe variant
const redStrWide: string = "Red" // wide, unspecific typed string
const c3 = Color[redStrWide as keyof typeof Color]
Safe variant with checks
const isEnumName = <T>(str: string, _enum: T): str is Extract<keyof T, string> =>
    str in _enum
const enumFromName = <T>(name: string, _enum: T) => {
    if (!isEnumName(name, _enum)) throw Error() // here fail fast as an example
    return _enum[name]
}
const c4 = enumFromName(redStrWide, Color)

转换字符串enum值

字符串枚举没有反向映射(与数字枚举相反)。我们可以创建一个查找助手来将枚举值字符串转换为枚举类型:

enum ColorStr { Red = "red", Green = "green" }

const c5_by_name = ColorStr["Red"] // ✅ this works
const c5_by_value_error = ColorStr["red"] // ❌ , but this not

const enumFromValue = <T extends Record<string, string>>(val: string, _enum: T) => {
    const enumName = (Object.keys(_enum) as Array<keyof T>).find(k => _enum[k] === val)
    if (!enumName) throw Error() // here fail fast as an example
    return _enum[enumName]
}

const c5 = enumFromValue("red", ColorStr)

操场上的样品