枚举
枚举
使用枚举我们可以定义一些带名字的常量。 使用枚举可以清晰地表达意图或创建一组有区别的用例。 TypeScript支持数字的和基于字符串的枚举。
数字枚举
首先我们看看数字枚举,如果你使用过其它编程语言应该会很熟悉。
enum Direction { Up = 1, Down, Left, Right }
如上,我们定义了一个数字枚举, Up
使用初始化为 1
。 其余的成员会从 1
开始自动增长。 换句话说, Direction.Up
的值为 1
, Down
为 2
, Left
为 3
, Right
为 4
。
我们还可以完全不使用初始化器:
enum Direction { Up, Down, Left, Right, }
现在, Up
的值为 0
, Down
的值为 1
等等。 当我们不在乎成员的值的时候,这种自增长的行为是很有用处的,但是要注意每个枚举成员的值都是不同的。
使用枚举很简单:通过枚举的属性来访问枚举成员,和枚举的名字来访问枚举类型:
enum Response { No = 0, Yes = 1, } function respond(recipient: string, message: Response): void { // ... } respond("Princess Caroline", Response.Yes)
数字枚举可以被混入到 计算过的和常量成员(如下所示)。 简短地说,不带初始化器的枚举或者被放在第一的位置,或者被放在使用了数字常量或其它常量初始化了的枚举后面。 换句话说,下面的情况是不被允许的:
enum E { A = getSomeValue(), B, // error! 'A' is not constant-initialized, so 'B' needs an initializer }
字符串枚举
字符串枚举的概念很简单,但是有细微的 运行时的差别。 在一个字符串枚举里,每个成员都必须用字符串字面量,或另外一个字符串枚举成员进行初始化。
enum Direction { Up = "UP", Down = "DOWN", Left = "LEFT", Right = "RIGHT", }
由于字符串枚举没有自增长的行为,字符串枚举可以很好的序列化。 换句话说,如果你正在调试并且必须要读一个数字枚举的运行时的值,这个值通常是很难读的 - 它并不能表达有用的信息(尽管 反向映射会有所帮助),字符串枚举允许你提供一个运行时有意义的并且可读的值,独立于枚举成员的名字。
异构枚举(Heterogeneous enums)
从技术的角度来说,枚举可以混合字符串和数字成员,但是似乎你并不会这么做:
enum BooleanLikeHeterogeneousEnum { No = 0, Yes = "YES", }
除非你真的想要利用JavaScript运行时的行为,否则我们不建议这样做。
计算的和常量成员
每个枚举成员都带有一个值,它可以是 常量或 计算出来的。 当满足如下条件时,枚举成员被当作是常量:
- 它是枚举的第一个成员且没有初始化器,这种情况下它被赋予值
0
:
// E.X is constant: enum E { X }
- 它不带有初始化器且它之前的枚举成员是一个 数字常量。 这种情况下,当前枚举成员的值为它上一个枚举成员的值加1。
// All enum members in 'E1' and 'E2' are constant. enum E1 { X, Y, Z } enum E2 { A = 1, B, C }
- 枚举成员使用 常量枚举表达式初始化。 常数枚举表达式是TypeScript表达式的子集,它可以在编译阶段求值。 当一个表达式满足下面条件之一时,它就是一个常量枚举表达式:
- 一个枚举表达式字面量(主要是字符串字面量或数字字面量)
- 一个对之前定义的常量枚举成员的引用(可以是在不同的枚举类型中定义的)
- 带括号的常量枚举表达式
- 一元运算符
+
,-
,~
其中之一应用在了常量枚举表达式 - 常量枚举表达式做为二元运算符
+
,-
,*
,/
,%
,<<
,>>
,>>>
,&
,|
,^
的操作对象。 若常数枚举表达式求值后为NaN
或Infinity
,则会在编译阶段报错。
所有其它情况的枚举成员被当作是需要计算得出的值。
enum FileAccess { // constant members None, Read = 1 << 1, Write = 1 << 2, ReadWrite = Read | Write, // computed member G = "123".length }