有什么方法可以让TypeScript枚举与JSON中的字符串兼容?
例如:
enum Type { NEW, OLD } interface Thing { type: Type } let thing:Thing = JSON.parse('{"type": "NEW"}'); alert(thing.type == Type.NEW); // false
我 想 thing.type == Type.NEW是真的。更具体地说,我希望可以将enum值定义为 字符串 ,而不是数字。
thing.type == Type.NEW
enum
我知道我可以使用,thing.type.toString() == Type[Type.NEW]但这很麻烦,而且似乎使枚举类型注释变得混乱和误导,从而违背了它的目的。JSON从技术上讲 不会 提供有效的枚举值,因此我不应该在枚举中键入属性。
thing.type.toString() == Type[Type.NEW]
所以我目前正在做的是使用带有静态常量的字符串类型:
const Type = { NEW: "NEW", OLD: "OLD" } interface Thing { type: string } let thing:Thing = JSON.parse('{"type": "NEW"}'); alert(thing.type == Type.NEW); // true
这为我提供了我想要的用法,但是类型注释string太宽泛并且容易出错。
string
我很惊讶JavaScript的超集没有基于字符串的枚举。我想念什么吗?有其他方法可以做到吗?
更新TS 1.8
使用字符串文字类型是另一种选择(感谢@basaret),但是要获得所需的类似枚举的用法(上面),它需要 两次 定义您的值:一次是字符串文字类型,一次是值(常量或名称空间):
type Type = "NEW" | "OLD"; const Type = { NEW: "NEW" as Type, OLD: "OLD" as Type } interface Thing { type: Type } let thing:Thing = JSON.parse(`{"type": "NEW"}`); alert(thing.type === Type.NEW); // true
这行得通,但要花很多时间,足以让我大部分时间不使用它。目前,我希望这项提案string enums最终能制定出路线图。
string enums
更新TS 2.1
新的keyof类型查找允许从const或名称空间的键生成字符串文字类型,这使定义 少了 一些冗余:
keyof
namespace Type { export const OLD = "OLD"; export const NEW = "NEW"; } type Type = keyof typeof Type; interface Thing { type: Type } const thing: Thing = JSON.parse('{"type": "NEW"}'); thing.type == Type.NEW // true
更新TS 2.4
TypeScript 2.4添加了对字符串枚举的支持!上面的示例变为:
enum Type { OLD = "OLD", NEW = "NEW" } interface Thing { type: Type } const thing: Thing = JSON.parse('{"type": "NEW"}'); alert(thing.type == Type.NEW) // true
这看起来 几乎是 完美的,但是仍然有些心痛:
OLD = "OLD"
NEW = "MEW"
enum Color { RED = "RED", BLUE = "BLUE", GREEN = "GREEN" } type ColorMap = { [P in Color]: number; } declare const color: Color; declare const map: ColorMap; map[color] // Error: Element implicitly has an 'any' type because type 'ColorMap' has no index signature. const red: Color = "RED"; // Type '"RED"' is not assignable to type 'Color'. const blue: Color = "BLUE" as "RED" | "BLUE" | "GREEN"; // Error: Type '"RED" | "BLUE" | "GREEN"' is not assignable to type 'Color'.
enum Color用字符串文字类型替换的等效代码可以正常工作…
enum Color
是的,我认为我对此有强迫症,我只想要我的完美JS枚举。:)
如果您在2.4版本之前使用Typescript,则可以通过将枚举值转换为来使用枚举来实现any。
any
首次实施的示例
enum Type { NEW = <any>"NEW", OLD = <any>"OLD", } interface Thing { type: Type } let thing:Thing = JSON.parse('{"type": "NEW"}'); alert(thing.type == Type.NEW); // true
Typescript 2.4已经内置了对字符串枚举的支持,因此,any不再需要强制转换为,而无需使用,就可以实现它String Literal Union Type,这对于验证和自动完成是可以的,但对于可读性和重构则不太好,具体取决于使用场景。
String Literal Union Type