我在TypeScript中定义了以下enum:
enum Color{
Red, Green
}
现在在我的函数中,我以字符串的形式接收颜色。我尝试了以下代码:
var green= "Green";
var color : Color = <Color>green; // Error: can't convert string to enum
如何将该值转换为enum?
我在TypeScript中定义了以下enum:
enum Color{
Red, Green
}
现在在我的函数中,我以字符串的形式接收颜色。我尝试了以下代码:
var green= "Green";
var color : Color = <Color>green; // Error: can't convert string to enum
如何将该值转换为enum?
当前回答
TS 3.9.x
var color : Color = Color[green as unknown as keyof typeof Color];
其他回答
打印稿1.倍
如果你确定输入字符串与Color enum完全匹配,那么使用:
const color: Color = (<any>Color)["Red"];
在输入字符串可能不匹配Enum的情况下,使用:
const mayBeColor: Color | undefined = (<any>Color)["WrongInput"];
if (mayBeColor !== undefined){
// TypeScript will understand that mayBeColor is of type Color here
}
操场上
如果我们没有将enum转换为<任意>类型,那么TypeScript将显示错误:
元素隐式具有“any”类型,因为索引表达式不是类型“number”。
这意味着默认情况下,TypeScript Enum类型与数字索引一起工作。 let c = Color[0],但是没有像let c = Color["string"]这样的字符串索引。这是微软团队针对更一般问题对象字符串索引的一个已知限制。
2.打印稿x-4x
TypeScript移动到typeof概念的键。
如果some使用字符串值enum:
enum Color {
Green = "GRN",
Red = "RD"
}
然后有语言解决方案映射键值(颜色。Green -> "GRN")只是通过访问枚举成员,但没有简单的方法来做相反的事情("GRN" -> Color.Green)。通过使用反向映射:
请记住,字符串enum成员不会得到反向映射 根本就不存在。
一种可能的解决方案是手动检查值并将值强制转换为enum。请注意,它只适用于字符串枚举。
function enumFromStringValue<T> (enm: { [s: string]: T}, value: string): T | undefined {
return (Object.values(enm) as unknown as string[]).includes(value)
? value as unknown as T
: undefined;
}
enumFromStringValue(Color, "RD"); // Color.Red
enumFromStringValue(Color, "UNKNOWN"); // undefined
enumFromStringValue(Color, "Red"); // undefined
提供的大多数答案都没有对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;
其他的变化可以是
const green= "Green";
const color : Color = Color[green] as Color;
对于Typescript >= 4,此代码工作:
enum Color{
Red, Green
}
// Conversion :
var green= "Green";
var color : Color = green as unknown as Color;
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;