简介
Enum 结构的特别之处在于,它既是一种类型,也是一个值。绝大多数 TypeScript 语法都是类型语法,编译后会全部去除,但是 Enum 结构是一个值,编译后会变成 JavaScript 对象,留在代码中
由于 TypeScript 的定位是 JavaScript 语言的类型增强,所以官方建议谨慎使用 Enum 结构,因为它不仅仅是类型,还会为编译后的代码加入一个对象。Enum 结构比较适合的场景是,成员的值不重要,名字更重要,从而增加代码的可读性和可维护性
TypeScript 5.0 之前,Enum 有一个 Bug,就是 Enum 类型的变量可以赋值为任何数值
由于 Enum 结构编译后是一个对象,所以不能有与它同名的变量(包括对象、函数、类等)
很大程度上,Enum 结构可以被对象的 as const 断言替代
上面示例中,对象 Bar 使用了 as const 断言,作用就是使得它的属性无法修改。这样的话,Foo 和 Bar 的行为就很类似了,前者完全可以用后者替代,而且后者还是 JavaScript 的原生数据结构
Enum 成员的值
同名 Enum 的合并
同名 Enum 的合并,最大用处就是补充外部定义的 Enum 结构
字符串 Enum
keyof 运算符
keyof 运算符可以取出 Enum 结构的所有成员名,作为联合类型返回
下面示例中,类型 Foo 等于类型 number 的所有原生属性名组成的联合类型
这是因为 Enum 作为类型,本质上属于 number 或 string 的一种变体,而 typeof MyEum 会将 MyEnum 当作一个值处理,从而先其转为对象类型,就可以再用 keyof 运算符返回该对象的所有属性名。如果要返回 Enum 所有的成员值,可以使用 in 运算符
上面示例中,采用属性索引可以取出 MyEum 的所有成员值
反向映射
数值 Enum 存在反向映射,即可以通过成员值获得成员名
上面示例中,Enum 成员 Wednesday 的值等于3,从而可以从成员值3取到对应的成员名 Wednesday,这就叫反向映射。这是因为 TypeScript 会将上面的 Enum 结构,编译成下面的 JavaScript 代码
上面代码中,实际进行了两组赋值,以第一个成员为例
上面代码有两个赋值运算符(=),实际上等同于下面的代码
注意,这种情况只发生在数值 Enum,对于字符串 Enum,不存在反向映射。这是因为字符串 Enum 编译后只有一组赋值