官网地址
枚举是 TypeScript 为数不多的不是 JavaScript 类型级扩展的特性之一。
枚举允许开发人员定义一组命名常量。 使用枚举可以更轻松地记录意图,或创建一组不同的案例。 TypeScript 提供数字和基于字符串的枚举。
Numeric enums
我们将首先从数字枚举开始,如果您在其他语言里使用过枚举类型,可能会更熟悉。 可以使用 enum 关键字定义枚举。
enum Direction {Up = 1,Down,Left,Right,}
上面的代码里,我们有一个数字枚举,其中 Up 初始化为 1。从那时起,以下所有成员都会自动递增。 换句话说,Direction.Up 的值为 1,Down 的值为 2,Left 的值为 3,Right 的值为 4。
如果省去 Up = 1,则默认从 0 开始给枚举值赋值。
运行时的枚举值
枚举是在运行时存在的真实对象。 例如,下面的枚举,可以作为形式参数的定义,传入到函数里:
enum E {X,Y,Z,}function f(obj: {X: number }) {return obj.X;}// Works, since 'E' has a property named 'X' which is a number.f(E);
上面的例子里,E.X 和 { X: number } 这两个类型是兼容的 - Compatible
Reverse mappings
使用反向映射,能够根据枚举的值拿到其名称。
除了为成员创建具有属性名称的对象之外,数字枚举成员还获得从枚举值到枚举名称的反向映射。 例如,在这个例子中:
enum Enum {A,}let a = Enum.A;let nameOfA = Enum[a]; // "A"
对应生成的 JavaScript 代码:
"use strict";var Enum;(function (Enum) {Enum[Enum["A"] = 0] = "A";})(Enum || (Enum = {}));let a = Enum.A;let nameOfA = Enum[a]; // "A"
在这个生成的代码中,一个枚举被编译成一个存储前向(名称 -> 值)和反向(值 -> 名称)映射的对象。 对其他枚举成员的引用始终作为属性访问发出,并且从不内联。
请记住,字符串枚举成员根本不会生成反向映射。
constenums
在大多数情况下,枚举是一个完全有效的解决方案。 然而,有时要求更严格。 为了避免在访问枚举值时支付额外生成的代码和额外的间接费用,可以使用 const 枚举。 Const 枚举是在我们的枚举上使用 const 修饰符定义的:
const enum Enum {A = 1,B = A * 2,}
常量枚举只能使用常量枚举表达式,并且与常规枚举不同,它们在编译期间被完全删除。 Const 枚举成员在使用站点内联。 这是可能的,因为 const 枚举不能有计算成员。
const enum Direction {Up,Down,Left,Right,}let directions = [Direction.Up,Direction.Down,Direction.Left,Direction.Right,];
上述代码转换成 JavaScript 之后:
"use strict";let directions = [0 /* Up */,1 /* Down */,2 /* Left */,3 /* Right */,];
另一个实际例子:
enum FakeUserAgent {Chrome = 'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36',InternetExplorer10 = 'Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)',InternetExplorer11 = 'WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; rv:11.0) like Gecko',Firefox = 'Win64; x64; rv:65.0) Gecko/0101 Firefox/65.0',};const nonInternetExplorerUserAgents: ReadonlyArray<string> =Object.entries(FakeUserAgent).filter(([browser]) =>!browser.toLowerCase().includes('internetexplorer')).map(([_browser, userAgent]) => userAgent);console.log(nonInternetExplorerUserAgents);
执行效果:
枚举字段里包含字符串 internetexplorer 的值被过滤了: