数字类型枚举
常规枚举的值都是数字类型,因此被称为数字类型枚举:
enum Color {
Red,
Blue,
Green
}
console.log(Color.Red);
// 0
console.log(Color[0]);
// Red
console.log(Color[Color.Red]);
// Red, Color.Red = 0
改变与数字枚举关联的数字
默认情况下,第一个枚举值是 0
,后续的值会递增。
可以通过赋值的方法修改枚举关联的数字,后续的值会递增,但不会修改之前的值:
enum Color {
Red, // 0
Blue = 2, // 2
Green // 3
}
手动赋值后,出现前面的值被后面的值覆盖了,但是 TypeScript 不会进行报错:
enum Color {
Red = 1, // 1
Blue = 0, // 0
Green // 1
}
console.log(Color['Red'] === 1); // true
console.log(Color['Green'] === 1); // true
console.log(Color[1] === 'Red'); // false
console.log(Color[1] === 'Green'); // true
字符串枚举
枚举的值还可以设置为字符串,当其中一个值赋值为字符串后,后续的值必须要赋值:
enum Color {
Red, // 0
Blue = 'Blue', // Blue
Green = 'Green' // Green
}
常量枚举
常量枚举可以提升些许的性能,在枚举值不会变化的情况下,最好都使用 const
进行声明:
const enum Color {
Red,
Blue,
Green
}
const red = Color.Red;
// 编译成 const red = 0 /* Red */;
常量枚举与普通枚举的区别是,它会在编译阶段被删除,并且不能包含计算成员。
const enum Color {
Red,
Blue,
Green
}
const red = Color.Red;
// 编译成
// var Color;
// (function (Color) {
// Color[Color["Red"] = 0] = "Red";
// Color[Color["Blue"] = 1] = "Blue";
// Color[Color["Green"] = 2] = "Green";
// })(Color || (Color = {}));
// const red = Color.Red;
计算所得项
枚举项有两种类型:常数项(constant member)和计算所得项(computed member)。
前面的例子使用的都是常数项,计算所得项其实就是通过计算才会得到最后的项:
enum Color {
Red,
Green,
Blue = 'blue'.length
}
计算所得项后面的值都需要进行手动赋值,否则会因为无法获得初始值而报错。
当满足以下条件时,枚举成员被当作是常数:
- 不具有初始化函数并且之前的枚举成员是常数。在这种情况下,当前枚举成员的值为上一个枚举成员的值加
1
。但第一个枚举元素是个例外。如果它没有初始化方法,那么它的初始值为0
。 枚举成员使用常数枚举表达式初始化。常数枚举表达式是 TypeScript 表达式的子集,它可以在编译阶段求值。当一个表达式满足下面条件之一时,它就是一个常数枚举表达式:
- 数字字面量
- 引用之前定义的常数枚举成员(可以是在不同的枚举类型中定义的)如果这个成员是在同一个枚举类型中定义的,可以使用非限定名来引用
带括号的常数枚举表达式 -
+
,-
,~
一元运算符应用于常数枚举表达式 -
+
,-
,*
,/
,%
,<<
,>>
,>>>
,&
,|
,^
二元运算符,常数枚举表达式做为其一个操作对象。若常数枚举表达式求值后为 NaN 或 Infinity,则会在编译阶段报错
所有其它情况的枚举成员被当作是需要计算得出的值。
外部枚举
外部枚举是使用 declare enum
定义的枚举类型:
declare enum Directions {
Up,
Down,
Left,
Right
}
const directions = [
Directions.Up,
Directions.Down,
Directions.Left,
Directions.Right
];
// 编译结果
const directions = [
Directions.Up,
Directions.Down,
Directions.Left,
Directions.Right
];
declare
定义的类型只会用于编译时的检查,编译结果中会被删除。
外部枚举和声明语句一样,常出现在声明文件中。同时使用 declare
和 const
是可以的:
declare const enum Directions {
Up,
Down,
Left,
Right
}
let directions = [
Directions.Up,
Directions.Down,
Directions.Left,
Directions.Right
];
// 编译结果
let directions = [0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */];