枚举
什么是枚举?:一些带名字的常量,类似于python的字典,ts支持基于数字和字符串的枚举。
数字枚举
enum Direction {
Up = 1,
Down,
Left,
Right
}
// Up 初始化为1 ,其他成员会自动增长。 Down = 2; Left = 3; Right = 4
// 如果完全不给初始值,就会从 0 开始自动增长
console.log(Direction.Up) // 访问枚举成员
没有初始化的枚举,要么放在第一的位置,要么放在被常量初始化后的枚举后面。
function getValue(): number {
return Math.random()*10
}
enum E {
A = getValue(),
B,
}
console.log(B) // error 因为 A 不是被常量赋值,所以B只能在A前面,不能在后面
字符串枚举
每个成员必须用字符串进行初始化
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT",
}
异构枚举
不推荐这样使用,混合数字枚举和字符串枚举
enum BooleanLikeHeterogeneousEnum {
No = 0,
Yes = "YES",
}
常量成员和计算成员
被当作常量成员的情况:
- 枚举的第一个成员,且没有初始化
- 没有初始化器,且之前的枚举成员是一个数字常量
- 枚举成员使用常量枚举表达式进行初始化。满足下列条件之一被看作常量枚举表达式
- 一个枚举表达式字面量
- 一个对之前定义的常量枚举成员的引用
- 带括号的常量枚举表达式
- 一元运算符
+
-
~
其中只有应用在了常量枚举表达式 - 常量枚举表达式为二元运算符
+
,-
,*
,/
,%
,<<
,>>
,>>>
,&
,|
,^
的操作对象;若求值之后为 NaN 或 Infinity 会编译时报错
所有的其他情况,被视作计算成员
enum FileAccess {
// constant members
None,
Read = 1 << 1,
Write = 1 << 2,
ReadWrite = Read | Write,
// computed member
G = "123".length
}
联合枚举与枚举成员的类型
字面量枚举成员
- 不带有初始值的常量枚举成员
- 任何字符串字面量(例如:
"foo"
,"bar"
,"baz"
) - 任何数字字面量(例如:
1
,100
) - 应用了一元
-
符号的数字字面量(例如:-1
,-100
)
当所有的枚举成员都拥有字面量枚举值时,枚举成员成为了类型
enum ShapeKind {
Circle,
Square,
}
interface Circle {
kind: ShapeKind.Circle;
radius: number;
}
interface Square {
kind: ShapeKind.Square;
sideLength: number;
}
let c: Circle = {
kind: ShapeKind.Square,
// ~~~~~~~~~~~~~~~~ Error! 因为Circle和Square已经成为一个类型,这里类型不相同。
radius: 100,
}
第二个变化:枚举类型本身成了每个枚举成员的联合。
举例一个愚蠢的错误
enum E {
Foo,
Bar,
}
function f(x: E) {
if (x !== E.Foo || x !== E.Bar) {
// ~~~~~~~~~~~
// x 要么是 E.Foo 要么是 E.Bar. 写出这样的屎山代码就会报错,因为无论如何都会执行。
}
}
运行时的枚举
在代码运行时,枚举是一个真正存在的对象
enum E {
X, Y, Z
}
function f(obj: { X:number }) {
return obj.X
} // Works
反向映射
可以从枚举值映射到枚举名字
enum Enum {
A
}
let a = Enum.A;
let nameOfA = Enum[a]; // "A"
外部枚举
外部枚举用来描述已经存在的枚举类型的形状
declare enum Enum {
A = 1,
B,
C = 2
} // 不明白
let a = Enum.A;
let nameOfA = Enum[a]; // “A”
## 外部枚举
外部枚举用来描述已经存在的枚举类型的形状
```typescript
declare enum Enum {
A = 1,
B,
C = 2
} // 不明白