简介

Enum 类型 - 图1

Enum 结构的特别之处在于,它既是一种类型,也是一个值。绝大多数 TypeScript 语法都是类型语法,编译后会全部去除,但是 Enum 结构是一个值,编译后会变成 JavaScript 对象,留在代码中

Enum 类型 - 图2

由于 TypeScript 的定位是 JavaScript 语言的类型增强,所以官方建议谨慎使用 Enum 结构,因为它不仅仅是类型,还会为编译后的代码加入一个对象。Enum 结构比较适合的场景是,成员的值不重要,名字更重要,从而增加代码的可读性和可维护性

Enum 类型 - 图3

TypeScript 5.0 之前,Enum 有一个 Bug,就是 Enum 类型的变量可以赋值为任何数值

Enum 类型 - 图4

由于 Enum 结构编译后是一个对象,所以不能有与它同名的变量(包括对象、函数、类等)

Enum 类型 - 图5

很大程度上,Enum 结构可以被对象的 as const 断言替代

Enum 类型 - 图6

上面示例中,对象 Bar 使用了 as const 断言,作用就是使得它的属性无法修改。这样的话,Foo 和 Bar 的行为就很类似了,前者完全可以用后者替代,而且后者还是 JavaScript 的原生数据结构

Enum 成员的值

Enum 类型 - 图7

Enum 类型 - 图8

Enum 类型 - 图9

同名 Enum 的合并

同名 Enum 的合并,最大用处就是补充外部定义的 Enum 结构

Enum 类型 - 图10

Enum 类型 - 图11

字符串 Enum

Enum 类型 - 图12

Enum 类型 - 图13

keyof 运算符

keyof 运算符可以取出 Enum 结构的所有成员名,作为联合类型返回

Enum 类型 - 图14

下面示例中,类型 Foo 等于类型 number 的所有原生属性名组成的联合类型

Enum 类型 - 图15

这是因为 Enum 作为类型,本质上属于 number 或 string 的一种变体而 typeof MyEum 会将 MyEnum 当作一个值处理,从而先其转为对象类型,就可以再用 keyof 运算符返回该对象的所有属性名。如果要返回 Enum 所有的成员值,可以使用 in 运算符

Enum 类型 - 图16

上面示例中,采用属性索引可以取出 MyEum 的所有成员值

反向映射

数值 Enum 存在反向映射,即可以通过成员值获得成员名

Enum 类型 - 图17

Enum 类型 - 图18

上面示例中,Enum 成员 Wednesday 的值等于3,从而可以从成员值3取到对应的成员名 Wednesday,这就叫反向映射。这是因为 TypeScript 会将上面的 Enum 结构,编译成下面的 JavaScript 代码

Enum 类型 - 图19

上面代码中,实际进行了两组赋值,以第一个成员为例

Enum 类型 - 图20

上面代码有两个赋值运算符(=),实际上等同于下面的代码

Enum 类型 - 图21

注意,这种情况只发生在数值 Enum,对于字符串 Enum,不存在反向映射。这是因为字符串 Enum 编译后只有一组赋值

Enum 类型 - 图22