Answers:
TypeScript 0.9中的枚举基于字符串+数字。对于简单的转换,您不需要类型断言:
enum Color{
Red, Green
}
// To String
var green: string = Color[Color.Green];
// To Enum / number
var color : Color = Color[green];
我在OSS书中有关于此枚举模式和其他枚举模式的文档:https : //basarat.gitbook.io/typescript/type-system/enums
var color : Color = Color[green as keyof typeof Color];
从Typescript 2.1开始,枚举中的字符串键是强类型的。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
let s = "Green"; let typedColor = <keyof typeof Color> s;
let
有const
意愿工作,而铸造。更新了示例以澄清这一点。感谢@SergeyT
typedColorString = Color["Black"];
现在返回error TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'
const color: Color = Color[colorString as keyof typeof Color];
如果您确定输入字符串与Color枚举完全匹配,请使用:
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
转换,<any>
那么TypeScript将显示错误:
元素隐式具有“任何”类型,因为索引表达式不是“数字”类型。
这意味着默认情况下,TypeScript Enum类型适用于数字索引,即
let c = Color[0]
,不适用于像的字符串索引let c = Color["string"]
。这是Microsoft团队对较普遍发行的Object string索引的已知限制。
typeof '0'
应该是string
enum Color{
Red, Green
}
// To String
var green: string = Color[Color.Green];
// To Enum / number
var color : Color = Color[green as keyof typeof Color]; //Works with --noImplicitAny
此示例可--noImplicitAny
在TypeScript中使用
来源:
https : //github.com/Microsoft/TypeScript/issues/13775#issuecomment-276381229 https://www.typescriptlang.org/docs/handbook/advanced-types.html#index-types
此注释与basarat的答案有关,而不是原始问题。
我在自己的项目中遇到了一个奇怪的问题,在该项目中,编译器使用以下代码给出的错误大致相当于“无法将字符串转换为颜色”:
var colorId = myOtherObject.colorId; // value "Green";
var color: Color = <Color>Color[colorId]; // TSC error here: Cannot convert string to Color.
我发现编译器类型推断变得混乱,并且认为这colorId
是枚举值而不是ID。要解决此问题,我必须将ID转换为字符串:
var colorId = <string>myOtherObject.colorId; // Force string value here
var color: Color = Color[colorId]; // Fixes lookup here.
我不确定是什么原因引起的,但是如果有人遇到与我同样的问题,我会在这里留下这张纸条。
如果您为枚举提供字符串值,则直接强制转换就可以了。
enum Color {
Green = "Green",
Red = "Red"
}
const color = "Green";
const colorEnum = color as Color;
如果TypeScript编译器知道变量的类型是字符串,则可以这样做:
let colorName : string = "Green";
let color : Color = Color[colorName];
否则,您应该将其显式转换为字符串(以避免编译器警告):
let colorName : any = "Green";
let color : Color = Color["" + colorName];
在运行时,两种解决方案都将起作用。
<string>colorName
而不是"" + colorName
?
这个问题有很多混杂的信息,因此让我们在Nick的使用TypeScript的模型中使用枚举指南中介绍 TypeScript 2.x +的整个实现。
本指南适用于:正在创建客户端代码的人员,这些代码正在从服务器中提取一组已知字符串,这些字符串可以方便地在客户端上建模为Enum。
让我们从枚举开始。它看起来应该像这样:
export enum IssueType {
REPS = 'REPS',
FETCH = 'FETCH',
ACTION = 'ACTION',
UNKNOWN = 'UNKNOWN',
}
这里有两点注意:
我们明确将它们声明为字符串支持的枚举类型,这使我们可以使用字符串而不是其他一些不相关的数字来实例化它们。
我们添加了一个服务器模型上可能存在或可能不存在的选项:UNKNOWN
。可以按照undefined
您的意愿进行处理,但是我希望尽可能避免| undefined
使用type来简化处理。
拥有UNKNOWN
案例的好处在于,您可以在代码中真正地看到它,并为未知枚举案例创建样式为鲜红色和闪烁的,因此您知道自己未正确处理某些事情。
您可能会使用嵌入在另一个模型中的枚举,也可能单独使用,但您必须将JSON或XML(ha)中的字符串型枚举解析为强类型的枚举。当嵌入另一个模型中时,此解析器将驻留在类构造函数中。
parseIssueType(typeString: string): IssueType {
const type = IssueType[typeString];
if (type === undefined) {
return IssueType.UNKNOWN;
}
return type;
}
如果枚举被正确解析,它将最终成为正确的类型。否则,undefined
您可以拦截它并退回您的UNKNOWN
案件。如果您希望将其undefined
用作未知情况,则可以只返回尝试进行枚举解析的任何结果。
从那里开始,只需使用parse函数和使用新的强类型变量即可。
const strongIssueType: IssueType = parseIssueType('ACTION');
// IssueType.ACTION
const wrongIssueType: IssueType = parseIssueType('UNEXPECTED');
// IssueType.UNKNOWN
IssueType["REPS"]="REPS"
。如果您对枚举定义了一些不同,例如,REPS="reps"
这将产生以下IssueType["REPS"]="reps"
结果
IssueType.UNKNOWN
因为reps
您的枚举中没有键。太糟糕了,我仍然没有找到可行的解决方案,因为我的字符串包含连字符,这使得它们不能用作键。
我需要知道如何遍历枚举值(正在测试多个枚举的排列),我发现这很好用:
export enum Environment {
Prod = "http://asdf.com",
Stage = "http://asdf1234.com",
Test = "http://asdfasdf.example.com"
}
Object.keys(Environment).forEach((environmentKeyValue) => {
const env = Environment[environmentKeyValue as keyof typeof Environment]
// env is now equivalent to Environment.Prod, Environment.Stage, or Environment.Test
}
资料来源:https : //blog.mikeski.net/development/javascript/typescript-enums-to-from-string/
each
一起使用,仅用一种方法测试每个枚举实例
我一直在寻找一个可以enum
从获取的答案string
,但就我而言,枚举值对应的字符串值不同。OP中有一个简单的枚举Color
,但我有一些不同之处:
enum Gender {
Male = 'Male',
Female = 'Female',
Other = 'Other',
CantTell = "Can't tell"
}
当您尝试Gender.CantTell
使用"Can't tell"
字符串进行解析时,它将返回undefined
原始答案。
基本上,我想出了另一个答案,这个答案强烈启发了我:
export const stringToEnumValue = <ET, T>(enumObj: ET, str: string): T =>
(enumObj as any)[Object.keys(enumObj).filter(k => (enumObj as any)[k] === str)[0]];
filter
,假设客户端从枚举传递一个有效的字符串。如果不是这种情况,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
。
请勿any
强制转换和正确键入。
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 MyEnum {
First,
Second,
Three
}
样本用法
const parsed = Parser.parseEnum('FiRsT', MyEnum);
// parsed = MyEnum.First
const parsedInvalid= Parser.parseEnum('other', MyEnum);
// parsedInvalid = undefined
忽略区分大小写的解析
class Parser {
public static parseEnum<T>(value: string, enumType: T): T[keyof T] | undefined {
if (!value) {
return undefined;
}
for (const property in enumType) {
const enumMember = enumType[property];
if (typeof enumMember === 'string') {
if (enumMember.toUpperCase() === value.toUpperCase()) {
const key = enumMember as string as keyof typeof enumType;
return enumType[key];
}
}
}
return undefined;
}
}
return enumType[property];
您的枚举项目看起来像个案件Skills = "anyvalue"
以您的方式创建的枚举被编译为一个对象,该对象存储正向(name -> value)
和反向(value -> name)
映射。正如我们从chrome devtools屏幕截图中所观察到的:
这是双重映射如何工作以及如何从一个映射到另一个的示例:
enum Color{
Red, Green
}
// To Number
var greenNr: number = Color['Green'];
console.log(greenNr); // logs 1
// To String
var greenString: string = Color[Color['Green']]; // or Color[Color[1]
console.log(greenString); // logs Green
// In your example
// recieve as Color.green instead of the string green
var green: string = Color[Color.Green];
// obtain the enum number value which corresponds to the Color.green property
var color: Color = (<any>Color)[green];
console.log(color); // logs 1
--noImplicitAny
(在VS中未选中的“允许隐式'any'类型”)。它error TS7017: Index signature of object type implicitly has an 'any' type.
为我产生了这项工作:(var color: Color = (<any>Color)[green];
经过1.4版测试)