我在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?
当前回答
简单的方法
enum Color { Red, Green }
const c1 = Color["Red"]
const redStr = "Red" // important: use `const`, not mutable `let`
const c2 = Color[redStr]
这既适用于数值枚举,也适用于字符串枚举。不需要使用类型断言。
未知enum字符串
Simple, unsafe variantconst 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)
操场上的样品
其他回答
如果TypeScript编译器知道变量的类型是字符串,那么这是可行的:
let colorName : string = "Green";
let color : Color = Color[colorName];
否则,你应该显式地将其转换为字符串(以避免编译器警告):
let colorName : any = "Green";
let color : Color = Color["" + colorName];
在运行时,两个解决方案都可以工作。
我正在寻找一个答案,可以从字符串中获得enum,但在我的情况下,enum值有不同的字符串值对应。OP有一个简单的枚举颜色,但我有一些不同的东西:
enum Gender {
Male = 'Male',
Female = 'Female',
Other = 'Other',
CantTell = "Can't tell"
}
当你试图解决性别问题时。CantTell与"Can't tell"字符串,它返回未定义的原始答案。
另一个答案
基本上,受到这个答案的强烈启发,我想出了另一个答案:
export const stringToEnumValue = <ET, T>(enumObj: ET, str: string): T =>
(enumObj as any)[Object.keys(enumObj).filter(k => (enumObj as any)[k] === str)[0]];
笔记
我们使用筛选器的第一个结果,假设客户端从枚举中传递一个有效的字符串。如果不是这样,则返回undefined。 我们将enumObj转换为any,因为在TypeScript 3.0+(目前使用TypeScript 3.5)中,enumObj被解析为unknown。
使用实例
const cantTellStr = "Can't tell";
const cantTellEnumValue = stringToEnumValue<typeof Gender, Gender>(Gender, cantTellStr);
console.log(cantTellEnumValue); // Can't tell
注意:而且,正如有人在评论中指出的那样,我还想使用noImplicitAny。
更新版本
没有对任何正确类型的强制转换。
export const stringToEnumValue = <T, 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];
此外,更新版本有一个更简单的方法来调用它,更可读:
stringToEnumValue(Gender, "Can't tell");
简单的方法
enum Color { Red, Green }
const c1 = Color["Red"]
const redStr = "Red" // important: use `const`, not mutable `let`
const c2 = Color[redStr]
这既适用于数值枚举,也适用于字符串枚举。不需要使用类型断言。
未知enum字符串
Simple, unsafe variantconst 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)
操场上的样品
从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
我还遇到了同样的编译器错误。只是Sly_cardinal方法的一个稍短的变种。
var color: Color = Color[<string>colorId];