枚举
枚举(Enum)类型用于取值被限定在一定范围内的场景,比如一周只能有七天,颜色限定为红绿蓝等
示例
使用枚举来定义关键字
enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
枚举成员会被赋值成从0开始,同行枚举名和值也会进行反向映射:
enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
console.log(Days[0] === 'Sun'); //true
console.log(Days['Sat'] === 6);//true
手动赋值
enum Days {Sun=7, Mon, Tue, Wed=1, Thu, Fri, Sat};
未被赋值的枚举项会接着上一个枚举项递增 如:
上面的枚举值会被编译成以下结果
{1: "Wed", 2: "Thu", 3: "Fri", 4: "Sat", 7: "Sun", 8: "Mon", 9: "Tue", Sun: 7, Mon: 8,
Tue: 9, Wed: 1, Thu: 2, Fri: 3, Sat: 4, Sun: 7, Mon: 8, Tue: 9 }
如果未被赋值的和手动赋值的重复了,TypeScript不会报错,后者会覆盖前者
所以使用的时候需要注意,最好不要出现这种覆盖的情况
手动赋值的枚举项可以不是数字,但是必须要使用类型断言来人tsc无视类型检查:
enum Days {Sun=7, Mon, Tue, Wed, Thu, Fri=({ value: 123, text: 'Fri'} as any), Sat=('Sat' as any)};
如果手动赋值的是非数字的话,手动赋值的枚举项后面也必须都要赋值,否则会报错:
enum Days {Sun=7, Mon, Tue, Wed, Thu, Fri=({ value: 123, text: 'Fri'} as any), Sat};
//Enum member must have initializer.
手动赋值也可以是小数或者负数,后续为赋值的项仍是递增加1
enum Days {Sun = 7, Mon = 1.5, Tue, Wed, Thu, Fri, Sat};
console.log(Days["Sun"] === 7); // true
console.log(Days["Mon"] === 1.5); // true
console.log(Days["Tue"] === 2.5); // true
console.log(Days["Sat"] === 6.5); // true
常数项和计算所得项
枚举项有两种类型:常数项(constant member)和计算所得项(computed member)。
enum Color {Red, Green, Blue = 'blue'.length};
'blue'.length
就是计算所得项;
如果紧接着计算所得项后面是未手动赋值的项,那么他就会因为无法获得初始值而报错:
enum Color {Red = 'red'.length, Green, Blue};
//Enum member must have initializer.
满足一下条件的枚举成员被当做是常数:
- 没有初始化函数并且之前的枚举成员是常数;这种情况下当前枚举成员的值是上一个成员+1;第一个枚举成员如果没有初始化,那么他的初始值为0
-
枚举成员使用常数枚举表达式初始化;常数枚举表达式是 TypeScript 表达式的子集,它可以在编译阶段求值。当一个表达式满足下面条件之一时,它就是一个常数枚举表达式:
- 数字字面量(即数字自己,不需要其他符号)
- 引用之前定义的常数枚举成员(可以是在不同的枚举类型中定义的)如果这个成员是在同一个枚举类型中定义的,可以使用非限定名来引用
- 带括号的常数枚举表达式
-
+
,-
,~
一元运算符应用于常数枚举表达式 -
+
,-
,*
,/
,%
,<<
,>>
,>>>
,&
,|
,^
二元运算符,常数枚举表达式做为其一个操作对象。若常数枚举表达式求值后为 NaN 或 Infinity,则会在编译阶段报错
常数枚举
常数枚举是使用 const enum
定义的枚举类型:
const enum Directions { up, down, left, right };
let directions = [Directions.up,Directions.down,Directions.left,Directions.right];
//[0, 1, 2, 3]
与普通枚举的区别是在编译阶段会被删除,并且不能包含计算成员。
const enum Color {Red, Green, Blue = 'blue'.length};
//const enum member initializers can only contain literal values and other computed enum values.
外部枚举
外部枚举用来描述已经存在的枚举类型的形状。
declare enum Directions { up, down, left, right };
let 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];
//[0, 1, 2, 3]