4

枚举

枚举(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 定义的类型只会用于编译时的检查,编译结果中会被删除。

外部枚举和非外部枚举之间有一个重要的区别,在正常的枚举里,没有初始化方法的成员被当成常数成员。 对于非常数的外部枚举而言,没有初始化方法时被当做需要经过计算的。

外部枚举与声明语句一样,常出现在声明文件中。

同时使用 declareconst 也是可以的:

declare const enum Directions { up, down, left, right };
let directions = [Directions.up,Directions.down,Directions.left,Directions.right];
//[0, 1, 2, 3]

兰俊秋雨
5.1k 声望3.5k 粉丝

基于大前端端技术的一些探索反思总结及讨论