我在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?
当前回答
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 2的整个实现。在Nick's Guide to Using Enums in Models with TypeScript中的x+。
本指南适用于:创建客户端代码的人,这些客户端代码从服务器获取一组已知字符串,这些字符串可以方便地在客户端建模为Enum。
定义枚举
让我们从枚举开始。它应该看起来像这样:
export enum IssueType {
REPS = 'REPS',
FETCH = 'FETCH',
ACTION = 'ACTION',
UNKNOWN = 'UNKNOWN',
}
这里需要注意两点:
我们显式地将这些声明为字符串支持的枚举情况,这允许我们用字符串来实例化它们,而不是其他一些不相关的数字。 我们添加了一个选项UNKNOWN,这个选项在我们的服务器模型上可能存在,也可能不存在。如果您愿意,可以将其处理为未定义,但我喜欢尽可能避免在类型上使用|未定义以简化处理。
使用UNKNOWN大小写的好处是,你可以在代码中非常明显地看到它,并为未知枚举大小写设置亮红色和闪烁的样式,这样你就知道你没有正确地处理某些事情。
解析枚举
您可以在另一个模型中使用这个枚举,或者单独使用这个枚举,但是您必须将字符串-y类型的枚举从JSON或XML (ha)解析为强类型的对应对象。当嵌入到另一个模型中时,这个解析器存在于类构造函数中。
parseIssueType(typeString: string): IssueType {
const type = IssueType[typeString];
if (type === undefined) {
return IssueType.UNKNOWN;
}
return type;
}
如果枚举被正确地解析,它将以正确的类型结束。否则,它将是未定义的,您可以拦截它并返回UNKNOWN情况。如果您更喜欢使用undefined作为未知情况,则可以直接返回尝试的enum解析的任何结果。
从这里开始,只需要使用parse函数和使用新创建的强类型变量。
const strongIssueType: IssueType = parseIssueType('ACTION');
// IssueType.ACTION
const wrongIssueType: IssueType = parseIssueType('UNEXPECTED');
// IssueType.UNKNOWN
我得到了它的工作使用以下代码。
var green= "Green";
var color : Color= <Color>Color[green];
其他的变化可以是
const green= "Green";
const color : Color = Color[green] as Color;
它在TypeScript 4.4.3 TS游乐场链接中为我工作。
const stringToEnumValue = <T extends Record<string, string>, K extends keyof T>(
enumObj: T,
value: string,
): T[keyof T] | undefined =>
enumObj[
Object.keys(enumObj).filter(
(k) => enumObj[k as K].toString() === value,
)[0] as keyof typeof enumObj
];
enum Color {
Red = 'red',
Green = 'green',
}
const result1 = stringToEnumValue(Color, 'yellow'); // undefined
const result2 = stringToEnumValue(Color, 'green'); // Color.Green
console.log(result1) // undefined = undefined
console.log(result2) // Color.Green = "green"
从Typescript 2.1开始,enum中的字符串键都是强类型的。Keyof typeof用于获取可用字符串键的信息(1):
enum Color{
Red, Green
}
let typedColor: Color = Color.Green;
let typedColorString: keyof typeof Color = "Green";
// Error "Black is not assignable ..." (indexing using Color["Black"] will return undefined runtime)
typedColorString = "Black";
// Error "Type 'string' is not assignable ..." (indexing works runtime)
let letColorString = "Red";
typedColorString = letColorString;
// Works fine
typedColorString = "Red";
// Works fine
const constColorString = "Red";
typedColorString = constColorString
// Works fine (thanks @SergeyT)
let letColorString = "Red";
typedColorString = letColorString as keyof typeof Color;
typedColor = Color[typedColorString];
https://www.typescriptlang.org/docs/handbook/advanced-types.html#index-types