TypeScript 的 Enum 类型

93 阅读3分钟

简介 经常需要定义一组相关的常量。将相关常量放在一个容器里面

enum Color {
  Red,     // 0
  Green,   // 1
  Blue     // 2
}

调用 Enum 的某个成员,与调用对象属性的写法一样,可以使用点运算符,也可以使用方括号运算符。 Enum 结构本身也是一种类型。

let c:Color = Color.Green; // 正确

Enum 结构比较适合的场景是,成员的值不重要,名字更重要,从而增加代码的可读性和可维护性。

enum Operator {
  ADD,
  DIV,
  MUL,
  SUB,
}

function compute(op: Operator, a: number, b: number) {
  switch (op) {
    case Operator.ADD:
      return a + b;
    case Operator.DIV:
      return a / b;
    case Operator.MUL:
      return a * b;
    case Operator.SUB:
      return a - b;
    default:
      throw new Error("wrong operator");
  }
}

compute(Operator.ADD, 1, 3); // 4

不能有与它同名的变量(包括对象、函数、类等) Enum 结构可以被对象的as const断言替代。

enum Foo {
  A,
  B,
  C,
}

const Bar = {
  A: 0,
  B: 1,
  C: 2,
} as const;

if (x === Foo.A){}
// 等同于
if (x === Bar.A) {}

Enum 成员的值 Enum 成员显式赋值 成员的值可以是任意数值,但不能是大整数 成员的值甚至可以相同 如果只设定第一个成员的值,后面成员的值就会从这个值开始递增。 Enum 成员的值也可以使用计算式。

enum Permission {
  UserRead     = 1 << 8,
  UserWrite    = 1 << 7,
  UserExecute  = 1 << 6,
  GroupRead    = 1 << 5,
  GroupWrite   = 1 << 4,
  GroupExecute = 1 << 3,
  AllRead      = 1 << 2,
  AllWrite     = 1 << 1,
  AllExecute   = 1 << 0,
}

enum Bool {
  No = 123,
  Yes = Math.random(),
}

Enum 成员值都是只读的,不能重新赋值

const enum Color {
  Red,
  Green,
  Blue
}

编译后依然将 Enum 转成对象,需要在编译时打开preserveConstEnums编译选项。 同名 Enum 的合并 多个同名的 Enum 结构会自动合并。 Enum 结构合并时,只允许其中一个的首成员省略初始值,否则报错。 同名 Enum 合并时,不能有同名成员,否则报错。 所有定义必须同为 const 枚举或者非 const 枚举,不允许混合使用。

字符串 Enum

字符串枚举的所有成员值,都必须显式设置。如果没有设置,成员值默认为数值,且位置必须在字符串成员之前。 变量类型如果是字符串 Enum,就不能再赋值为字符串

enum MyEnum {
  One = 'One',
  Two = 'Two',
}

let s = MyEnum.One;
s = 'One'; // 报错

字符串 Enum 作为一种类型,有限定函数参数的作用

const enum MediaTypes {
  JSON = 'application/json',
  XML = 'application/xml',
}

const url = 'localhost';

fetch(url, {
  headers: {
    Accept: MediaTypes.JSON,
  },
}).then(response => {
  // ...
});

字符串 Enum 可以使用联合类型(union)代替。

function move(
  where:'Up'|'Down'|'Left'|'Right'
) {
  // ...
 }

字符串 Enum 的成员值,不能使用表达式赋值。

enum MyEnum {
  A = 'one',
  B = ['T', 'w', 'o'].join('') // 报错
}

keyof 运算符

keyof 运算符可以取出 Enum 结构的所有成员名,作为联合类型返回。

enum MyEnum {
  A = 'a',
  B = 'b'
}

// 'A'|'B'
type Foo = keyof typeof MyEnum;

typeof是必需的,否则keyof MyEnum相当于keyof number。 Enum 作为类型,本质上属于numberstring的一种变体,而typeof MyEnum会将MyEnum当作一个值处理,从而先其转为对象类型,就可以再用keyof运算符返回该对象的所有属性名。 如果要返回 Enum 所有的成员值,可以使用in运算符。

enum MyEnum {
  A = 'a',
  B = 'b'
}

// { a: any, b: any }
type Foo = { [key in MyEnum]: any }

反向映射

enum Weekdays {
  Monday = 1,
  Tuesday,
  Wednesday,
  Thursday,
  Friday,
  Saturday,
  Sunday
}

console.log(Weekdays[3]) // Wednesday

字符串 Enum,不存在反向映射