我在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?
当前回答
从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
其他回答
Typescript 3.9提案
enum Color{ RED, GREEN }
const color = 'RED' as Color;
容易peasy……柠檬捏的!
这个笔记与basarat的回答有关,而不是最初的问题。
我在自己的项目中遇到了一个奇怪的问题,编译器给出了一个大致相当于“不能将字符串转换为颜色”的错误,使用这段代码的等价物:
var colorId = myOtherObject.colorId; // value "Green";
var color: Color = <Color>Color[colorId]; // TSC error here: Cannot convert string to Color.
我发现编译器的类型推断变得混乱,它认为colorId是一个enum值,而不是一个ID。为了解决这个问题,我必须将ID转换为字符串:
var colorId = <string>myOtherObject.colorId; // Force string value here
var color: Color = Color[colorId]; // Fixes lookup here.
我不确定是什么导致了这个问题,但我会在这里留下这张便条,以防有人遇到和我一样的问题。
简单的方法
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)
操场上的样品
提供的大多数答案都没有对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;
我还遇到了同样的编译器错误。只是Sly_cardinal方法的一个稍短的变种。
var color: Color = Color[<string>colorId];