枚举

数字枚举

  1. enum Direction {
  2. Up = 1,
  3. Down,
  4. Left,
  5. Right
  6. }
  7. // 数字枚举
  8. enum Direction {
  9. Up,
  10. Down,
  11. Left,
  12. Right,
  13. }

字符串枚举

  1. enum Direction {
  2. Up = "UP",
  3. Down = "DOWN",
  4. Left = "LEFT",
  5. Right = "RIGHT",
  6. }

异构枚举

除非想要利用JavaScript运行时的行为,否则我们不建议这样做

  1. enum BooleanLikeHeterogeneousEnum {
  2. No = 0,
  3. Yes = "YES",
  4. }

使用举例

  1. enum Response {
  2. No = 0,
  3. Yes = 1,
  4. }
  5. function respond(recipient: string, message: Response): void {
  6. // ...
  7. }
  8. respond("Princess Caroline", Response.Yes)

计算和常量成员

每个枚举成员都带有一个值,他可以是常量或者是计算出来的。
常量枚举值的几个条件。

  • 且没有初始化器枚举的第一个成员,默认赋值0。
  • 没有初始化器,它之前的枚举成员是一个数字常量,当前值是上一个枚举成员值加1。
  • 枚举成员使用常量枚举表达式初始化。常量枚举表达式是TypeScript表达式的自己,可以在编译阶段求值。
  • 所有其他情况的枚举成员,被当作是需要计算得出的值。

常量枚举表达式的几个条件

  • 一个枚举表达式字面量(主要是字符串字面量或数字字面量)
  • 一个对之前定义的常量枚举成员的引用(可以是在不同枚举类型中定义的)
  • 带括号的常量枚举表达式。
  • 一元运算符+,-,~其中之一应用在了常量枚举表达式
  • 常量枚举表达式作为二元运算符+, -, *, /, %, <<, >>, >>>, &, |, ^的操作对象。 若常数枚举表达式求值后为 NaN或 Infinity,则会在编译阶段报错。

联合枚举与枚举成员的类型

字面量枚举成员
字面量枚举成员是是一种特殊的非计算的常量枚举成员的子集。字面量枚举成员指不带有初始值的常量枚举成员,或者值被初始化为任何字符串字面量,任何数字字面量,应用了一元-符号的数字字面量(例如:-1,-100)

所有枚举成员都拥有字面量枚举值时,枚举值的特殊意义:枚举成员成为了类型、枚举类型本身变成了每个枚举成员的联合。

实用举例

  1. enum E {
  2. Foo,
  3. Bar,
  4. }
  5. function f(x: E) {
  6. if (x !== E.Foo || x !== E.Bar) {
  7. // ~~~~~~~~~~~
  8. // Error! Operator '!==' cannot be applied to types 'E.Foo' and 'E.Bar'.
  9. }
  10. }
  11. 这个例子里,我们先检查 x是否不是 E.Foo 如果通过了这个检查,然后 ||会发生短路效果, if语句体里的内容会被执行。 然而,这个检查没有通过,那么 x 只能为 E.Foo,因此没理由再去检查它是否为 E.Bar

运行时的枚举

枚举是在运行时真正存在的对象。

反响映射

  1. enum Enum {
  2. A
  3. }
  4. let a = Enum.A;
  5. let nameOfA = Enum[a]; // "A"
  1. var Enum;
  2. (function (Enum) {
  3. Enum[Enum["A"] = 0] = "A";
  4. })(Enum || (Enum = {}));
  5. var a = Enum.A;
  6. var nameOfA = Enum[a]; // "A"

枚举类型被编译成一个对象,它包含了正向映射( name -> value)和反向映射( value -> name)。 引用枚举成员总会生成为对属性访问并且永远也不会内联代码。不会为字符串枚举成员生成反向映射。

const枚举

避免在额外生成的代码上的开销和额外的非直接的对枚举成员的访问。

  1. const enum Enum {
  2. A = 1,
  3. B = A * 2
  4. }
  5. let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right]
  1. var directions = [0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */];

常量枚举只能用常量枚举表达式,与常规枚举不同的是,会在编译阶段被删除常量枚举成员在使用的地方会被内联进来。因为常量枚举不包含计算成员。

外部枚举

外部枚举用来描述已经存在的枚举类型的形状。

  1. declare enum Enum {
  2. A = 1,
  3. B,
  4. C = 2
  5. }

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