【发布时间】:2016-06-16 01:34:57
【问题描述】:
有没有办法让 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.toString() == Type[Type.NEW],但这很麻烦,并且似乎使枚举类型注释令人困惑和误导,这违背了它的目的。 JSON 在技术上不提供有效的枚举值,所以我不应该将属性键入枚举。
所以我目前正在做的是使用带有静态常量的字符串类型:
const Type = { NEW: "NEW", OLD: "OLD" }
interface Thing { type: string }
let thing:Thing = JSON.parse('{"type": "NEW"}');
alert(thing.type == Type.NEW); // true
这得到了我想要的用法,但是类型注释 string 过于宽泛且容易出错。
我有点惊讶 JavaScript 的超集没有基于字符串的枚举。我错过了什么吗?有没有不同的方法可以做到这一点?
更新 TS 1.8
使用string literal types 是另一种选择(感谢@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
这可行,但需要大量样板文件,足以让我大部分时间都不使用它。现在我希望proposal for string enums 最终会制定路线图。
更新 TS 2.1
新的keyof type lookup 允许从 const 或命名空间的键生成字符串字面量类型,这使得定义的冗余度少了:
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 added support for string enums!上面的例子变成:
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替换为字符串文字类型的等效代码可以正常工作...
是的,我想我对此有强迫症,我只想要完美的 JS 枚举。 :)
【问题讨论】:
标签: json enums typescript