typeScript-枚举

枚举

枚举(Enum)类型用于取值被限定在一定范围内的场景,比如一周只能有七天,颜色限定为红绿蓝等。

创建枚举

enum 枚举名称 {成员1,成员2,成员3}

创建枚举通过enum关键字创建,关键字后面加上枚举名称,在后面加上花括号,花括号里面放入枚举的成员,枚举成员可以有多个。枚举名称、成员名称收个字母大写,多个成员之间用逗号隔开。

示例
enum Family {Mom, Father, me}

枚举成员会被赋值为从0开始递增的数字,同时也会对枚举值到枚举名进行反向映射

enum Days {Sun, Mon, Tue, Med, Thu, Fri, Sat}
  console.log(Days[0] === 'Sun') // true
  console.log(Days[1] === 'Mon') // true
  console.log(Days[2] === 'Tue') // true
  console.log(Days[6] === 'Sat') // true
  console.log(Days['Sun'] === 0) // true
  console.log(Days['Mon'] === 1) // true

实时上,上面的例子会被编译为

var Days;
(function(Days) {
  Days[Days['Sun'] = 0] = 'Sun';
 Days[Days['Mon'] = 1] = 'Mon';
Days[Days['Tue'] = 2] = 'Tue';
Days[Days['Med'] = 3] = 'Med';
Days[Days['Thu'] = 4] = 'Thu';
Days[Days['Fri'] = 5] = 'Fri';
Days[Days['Sat'] = 6] = 'Sat';
})(Days)

手动赋值

我们也可以给枚举项手动赋值

enum Days{Sun=7,Mon=1,Tue,Wed,Thu,Fri,Sat}
  console.log(Days['Sun'] === 7) // true
  console.log(Days['Mon'] === 1)// true
  console.log(Days['Tue'] === 2)// true
  console.log(Days['Wed'] === 3)// true
  console.log(Days['Thu'] === 4)// true
  console.log(Days['Fri'] === 5)// true
  console.log(Days['Sat'] === 6)// true

上面例子中,为手动赋值的枚举项会接着上一个枚举项递增

如果为手动赋值的枚举项与手动赋值的重复了,TypeScript是不会察觉到这一点的

 enum Days {Sun = 3,Mon=1,Tue,Wed,Thu,Fri,Sat}
  console.log(Days['Sun'] === 3) // true
  console.log(Days['Wed'] === 3) // true
  console.log(Days[3] === 'Sun') // false
  console.log(Days[3] === 'Wed') // true

上面的例子中,递增到3的时候与前面的Sun的取值重复了,但是TypeScript并没有报错,导致Days[3]的值显示"Sun",而后又被"wed"覆盖了

编译的结果是

var Days;
(function (Days) {
    Days[Days["Sun"] = 3] = "Sun";
    Days[Days["Mon"] = 1] = "Mon";
    Days[Days["Tue"] = 2] = "Tue";
    Days[Days["Wed"] = 3] = "Wed";
    Days[Days["Thu"] = 4] = "Thu";
    Days[Days["Fri"] = 5] = "Fri";
    Days[Days["Sat"] = 6] = "Sat";
})(Days || (Days = {}));

所以使用的时候,最好不要出现这种覆盖的情况

手动赋值的枚举项,可以不是数字。此时需要使用类型断言来让tsc无视类型检查(编译出来的js仍然是可用的)

enum Days {Sun = 7,Mon,Tue,Wed,Thu,Fri,Sat=<any>'S'}

编译结果如下

var Days;
(function (Days) {
    Days[Days["Sun"] = 7] = "Sun";
    Days[Days["Mon"] = 8] = "Mon";
    Days[Days["Tue"] = 9] = "Tue";
    Days[Days["Wed"] = 10] = "Wed";
    Days[Days["Thu"] = 11] = "Thu";
    Days[Days["Fri"] = 12] = "Fri";
    Days[Days["Sat"] = "S"] = "Sat";
})(Days || (Days = {}));

当然,手动赋值的枚举项也可以为小数或负数,此时后续未手动赋值的项递增步长仍然为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 Colors {Red, Yellow, Blue='blue'.length}
  console.log(Colors) // {0: 'Red', 1: 'Yellow', 4: 'Blue', Red: 0, Yellow: 1, Blue: 4}

上面例子中,'blue'.length就是一个计算所得项

上面的例子不会报错,但是如果紧接在计算所得项后面的是为手动赋值项,那么它就会因为无法获得初始值而报错。

enum Color {Red = 'red'.length, Yellow='yellow'.length}
  console.log(Color) //{3: 'Red', 6: 'Yellow', Red: 3, Yellow: 6}
  enum Color2{Red = 'red'.length, Yellow='yellow'.length, Green} // Enum member must have initializer.

下面是常数项和计算所得项的完整定义

当满足一下条件时,枚举成员被当做是常数

  • 不具有初始化函数并且之前的枚举成员是常数,在这种情况下,当前枚举成员的值为上一个枚举成员的值加1.但第一个枚举元素是个例外。如果他没有初始化方法,那么它的初始值为0
  • 枚举成员使用常数枚举表达式初始化。常数枚举表达式是TypeScript表达式的子集,它可以在编译阶段求值。当一个表达式满足下面条件之一时,他就是一个常数枚举表达式。
    • 数字字面量
    • 引用之前定义的常数枚举成员(可以是在不同的枚举类型中定义的)如果这个成员是在同一个枚举类型中定义的,可以使用非限定名来引用
    • 带括号的常数枚举表达式
    • +, -, ~ 一元运算符应用于常数枚举表达式
    • +, -, *, /, %, <<, >>, >>>, &, |, ^ 二元运算符,常数枚举表达式做为其一个操作对象。若常数枚举表达式求值后为 NaN 或 Infinity,则会在编译阶段报错
posted @ 2022-03-30 16:38  upupupupupgo  阅读(55)  评论(0编辑  收藏  举报