有没有办法让文字枚举与JSON中的字符串兼容?
例如:
enum Type { NEW, OLD }
interface Thing { type: Type }
let thing:Thing = JSON.parse('{"type": "NEW"}');
alert(thing.type == Type.NEW); // false
我希望这是真的.或者更具体地说,我希望我可以将enum
个值指定为strings,而不是数字.
我知道我可以使用thing.type.toString() == Type[Type.NEW]
,但这很麻烦,而且似乎使枚举类型注释令人困惑和误导,这违背了它的目的.从技术上讲,JSON是not,提供一个有效的枚举值,所以我不应该向枚举键入属性.
So what I am currently doing instead is using a string type with static constants:
const Type = { NEW: "NEW", OLD: "OLD" }
interface Thing { type: string }
let thing:Thing = JSON.parse('{"type": "NEW"}');
alert(thing.type == Type.NEW); // true
这就得到了我想要的用法,但是类型注释string
太宽泛,而且容易出错.
I'm a bit surprised that a superset of JavaScript doesn't have string based enums. Am I missing something? Is there a different way this can be done?
Update TS 1.8
Using string literal types is another alternative (thanks @basaret), but to get the desired enum-like usage (above) it requires defining your values twice: once in a string literal type, and once as a value (constant or namespace):
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
This works but takes a lot of boilerplate, enough that I don't use it most of the time. For now I'm hoping the proposal for string enums
will eventually make the roadmap.
Update TS 2.1
The new keyof
type lookup allows for the string literal type to be generated from the keys of a const or namespace, which makes the definition a little less redundant:
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
Update TS 2.4
TypeScript 2.4 added support for string enums! The above example becomes:
enum Type {
OLD = "OLD",
NEW = "NEW"
}
interface Thing { type: Type }
const thing: Thing = JSON.parse('{"type": "NEW"}');
alert(thing.type == Type.NEW) // true
This looks nearly perfect, but there's still some heartache:
- 你必须写两次值,即
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枚举.:)