使用枚举我们可以定义一些带名字的常量。 使用枚举可以清晰地表达意图或创建一组有区别的用例。枚举类型使用 enum 关键字。
枚举的类型
数字枚举 Numeric enums
export enum Day {Monday = 1,Tuesday = 2,Wednesday = 3,Thursday = 4,Friday = 5,Saturday = 6,Sunday = 7,}
字符串枚举 String enums
enum Direction {Up = "UP",Down = "DOWN",Left = "LEFT",Right = "RIGHT",}
异构枚举 Heterogeneous enums
数字类型和字符串类型可以混合使用,但是不建议:
enum BooleanLikeHeterogeneousEnum {No = 0,Yes = "YES",}
枚举成员
计算成员和常量成员 Computed and constant members
enum FileAccess {// constant membersNone,Read = 1 << 1,Write = 1 << 2,ReadWrite = Read | Write,// computed memberG = "123".length,}
Union enums and enum member types
运行时和编译时
枚举在运行时 Enums at runtime
枚举是在运行时真正存在的对象,可以被传递到方法中:
enum E {X,Y,Z,}function f(obj: { X: number }) {return obj.X;}// works, E含有X属性f(E);
枚举在编译时 Enums at compile time
即使枚举是在运行时存在的真实对象,关键字 keyof 与对象的运行方式又是不同的。我们使用 keyof typeof 来获得一个将所有Enum键表示为字符串的类型。
enum LogLevel {ERROR,WARN,INFO,DEBUG,}/*** This is equivalent to:* type LogLevelStrings = 'ERROR' | 'WARN' | 'INFO' | 'DEBUG';*/type LogLevelStrings = keyof typeof LogLevel;function printImportant(key: LogLevelStrings, message: string) {const num = LogLevel[key];if (num <= LogLevel.WARN) {console.log("Log level key is:", key);console.log("Log level value is:", num);console.log("Log level message is:", message);}}printImportant("ERROR", "This is a message");
正向映射和反向映射
数字枚举成员具有反向映射:
enum Enum {
A,
}
let a = Enum.A; // 0
let nameOfA = Enum[a]; // "A"
TypeScript可能会将这段代码编译为下面的JavaScript:
"use strict";
var Enum;
(function (Enum) {
Enum[Enum["A"] = 0] = "A";
})(Enum || (Enum = {}));
let a = Enum.A;
let nameOfA = Enum[a]; // "A"
生成的代码中,枚举类型被编译成一个对象,它包含了正向映射( name -> value)和反向映射( value -> name)。
要注意的是:不会为字符串枚举成员生成反向映射。
枚举的定义
enum
当我们定义一个枚举
enum Cheese { Brie, Cheddar }
编译器将编译为:
var Cheese;
(function (Cheese) {
Cheese[Cheese["Brie"] = 0] = "Brie";
Cheese[Cheese["Cheddar"] = 1] = "Cheddar";
})(Cheese || (Cheese = {}));
所以我们可以正向映射或反向映射:
// Evaluates to 0 at runtime
Cheese.Brie;
// Evaluates to 'Brie' at runtime
Cheese[0];
const enum
当我们定义一个const枚举:
const enum Bread { Rye, Wheat }
不会有任何代码编译输出。只有当我们访问:
const rye = Bread.Rye
// or
const rye = Bread['Rye']
只剩下常量 rye。当如果你访问:
// Compiler error. const enums don't provide reverse lookup.
// Bread[0]
运行时就会报错。
Note:如果tsconfig 打开配置项 --preserveConstEnums ,编译结果将会和定义普通enum一样。
declare enum
官方文档也叫 Ambient enums
定义一个外部枚举:
declare enum Wine { Red, Wine }
也不会编译出任何代码。它是用来描述已经存在的枚举类型的形状。
declare const enum
declare const enum Fruit { Apple, Pear }
Objects vs Enums
const enum EDirection {
Up,
Down,
Left,
Right,
}
const ODirection = {
Up: 0,
Down: 1,
Left: 2,
Right: 3,
} as const;
EDirection.Up;
// ^ = (enum member) EDirection.Up = 0
ODirection.Up;
// ^ = (property) Up: 0
// Using the enum as a parameter
function walk(dir: EDirection) {}
// It requires an extra line to pull out the keys
type Direction = typeof ODirection[keyof typeof ODirection];
function run(dir: Direction) {}
walk(EDirection.Left);
run(ODirection.Right);
参考:
- Enums (官方英文文档)
- 枚举
- TypeScript enums explained (比较了enum, const enum, declare enum, and declare const enum identifiers.)
