官网地址
枚举是 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/20100101 Firefox/65.0', }; const nonInternetExplorerUserAgents: ReadonlyArray<string> = Object.entries(FakeUserAgent) .filter(([browser]) => !browser.toLowerCase().includes('internetexplorer')) .map(([_browser, userAgent]) => userAgent); console.log(nonInternetExplorerUserAgents);
执行效果:
枚举字段里包含字符串 internetexplorer 的值被过滤了: