10. Enum类型(枚举)
enum(枚举)在 TypeScript 中是一个用于定义一组命名常量的工具,它可以让代码更加清晰、可读、可维护。
假设你有一组固定的值,比如一周的七天、订单状态、用户角色、性别等等。用字符串或数字硬编码是很容易出错的,比如:
if (status === 'shipped') { ... } // ❌ 拼写错了就错
Enum 结构的特别之处在于,**它既是一种类型,也是一个值。**绝大多数 TypeScript 语法都是类型语法,编译后会全部去除,但是 Enum 结构是一个值,编译后会变成 JavaScript 对象,留在代码中。
// 编译前
enum Color {
Red, // 0
Green, // 1
Blue // 2
}
// 编译后
let Color = {
Red: 0,
Green: 1,
Blue: 2
};
由于 TypeScript 的定位是 JavaScript 语言的类型增强,所以官方建议谨慎使用 Enum 结构,因为它不仅仅是类型,还会为编译后的代码加入一个对象。
Enum 结构比较适合的场景是,成员的值不重要,名字更重要,从而增加代码的可读性和可维护性。
另外,由于 Enum 结构编译后是一个对象,所以不能有与它同名的变量(包括对象、函数、类等)。
Enum 成员默认不必赋值,系统会从零开始逐一递增,按照顺序为每个成员赋值,比如0、1、2……
enum Color {
Red,
Green,
Blue
}
// 等同于
enum Color {
Red = 0,
Green = 1,
Blue = 2
}
如果只设定第一个成员的值,后面成员的值就会从这个值开始递增。
enum Color {
Red = 7,
Green, // 8
Blue // 9
}
// 或者
enum Color {
Red, // 0
Green = 7,
Blue // 8
}
成员的值可以是任意数值,但不能是大整数(Bigint)。成员的值甚至可以相同。
Enum 成员值都是只读的,不能重新赋值。通常会在 enum
关键字前面加上const修饰,表示这是常量,不能再次赋值。
const enum Color {
Red,
Green,
Blue
}
多个同名的 Enum 结构会自动合并。Enum 结构合并时,只允许其中一个的首成员省略初始值,否则报错。
Enum 成员的值除了设为数值,还可以设为字符串。也就是说,Enum 也可以用作一组相关字符串的集合。
注意,字符串枚举的所有成员值,都必须显式设置。如果没有设置,成员值默认为数值,且位置必须在字符串成员之前。
enum Foo {
A, // 0
B = 'hello',
C // 报错
}
除了数值和字符串,Enum 成员不允许使用其他值(比如 Symbol 值)。
keyof 运算符可以取出 Enum 结构的所有成员名,作为联合类型返回
enum MyEnum {
A = 'a',
B = 'b'
}
// 'A'|'B'
type Foo = keyof typeof MyEnum
注意,这里的typeof是必需的,否则keyof MyEnum相当于keyof string
数值 Enum 存在反向映射,即可以通过成员值获得成员名。
enum Weekdays {
Monday = 1,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
}
console.log(Weekdays[3]) // Wednesday
上面示例中,Enum 成员Wednesday的值等于3,从而可以从成员值3取到对应的成员名Wednesday,这就叫反向映射。
注意,这种情况只发生在数值 Enum,**对于字符串 Enum,不存在反向映射。**这是因为字符串 Enum 编译后只有一组赋值。
双向映射可能会导致一些类型推断的问题。如果不需要双向映射,推荐用字符串枚举。
使用Enum的优点
可读性高:用名字代替数字或字符串常量
安全:有类型检查,防止拼写错误
可维护:集中管理固定的状态/常量集
智能提示:IDE 支持补全和跳转
字符串枚举更直观:更适合现代开发场景
评论