1、定义
1)使用枚举可以清晰地表达意图或创建一组有区别的用例;
2)TypeScript支持数字的和基于字符串的枚举。
2、分类
1)数字枚举
enum Direction {
Up = 1,
Down,
Left,
Right
}
//数字枚举, Up使用初始化为 1。 其余的成员会从 1开始自动增长。
//换句话说, Direction.Up的值为 1, Down为 2, Left为 3, Right为 4。
使用的案例
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 }
2)字符串枚举
每个成员都使用,字符串字面量来初始化
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT",
}
3)异构枚举(Heterogeneous enums)
enum BooleanLikeHeterogeneousEnum {
No = 0,
Yes = "YES",
}
4)计算的和常量成员
无值,则会有默认值0
// E.X is constant:
enum E { X }
//这种情况下它被赋予值 0
第一个有初始值,那么就+1
// All enum members in 'E1' and 'E2' are constant.
enum E1 { X, Y, Z }
enum E2 {
A = 1, B, C
}
其他需要计算出值的情况
- 一个枚举表达式字面量(主要是字符串字面量或数字字面量)
- 一个对之前定义的常量枚举成员的引用(可以是在不同的枚举类型中定义的)
- 带括号的常量枚举表达式
- 一元运算符
+
,-
,~
其中之一应用在了常量枚举表达式 - 常量枚举表达式做为二元运算符
+
,-
,*
,/
,%
,<<
,>>
,>>>
,&
,|
,^
的操作对象。 若常数枚举表达式求值后为NaN
或Infinity
,则会在编译阶段报错。
enum FileAccess {
// constant members
None,
Read = 1 << 1,
Write = 1 << 2,
ReadWrite = Read | Write,
// computed member
G = "123".length
}
联合枚举与枚举成员的类型
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!
radius: 100,
}
这里不大明白,为什么会报错,
明白了,在接口里是类型;在对象里是属性值,所以报错了。
意味着,枚举不能两者都是,做了类型。就不能是值了?[待验证]
另一个变化是枚举类型本身变成了每个枚举成员的 联合。
enum E {
Foo,
Bar,
}
function f(x: E) {
if (x !== E.Foo || x !== E.Bar) {
// ~~~~~~~~~~~
// Error! Operator '!==' cannot be applied to types 'E.Foo' and 'E.Bar'.
}
}
理解的是,既做了类型,又做值的比较就会有问题。
运行时的枚举
//枚举是在运行时真正存在的对象
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);
反向映射
enum Enum {
A
}
let a = Enum.A;
let nameOfA = Enum[a]; // "A"
//编译为JavaScript为
var Enum;
(function (Enum) {
Enum[Enum["A"] = 0] = "A";
})(Enum || (Enum = {}));
var a = Enum.A;
var nameOfA = Enum[a]; // "A"
相当于知道属性值,来知道属性。这个功能感觉挺强大。前提是,属性值不重复。
问题来了,假如重复了,是会报错,还是找到两个?
仅限于数字枚举。
不会为字符串枚举成员生成反向映射
const
枚举
const enum Enum {
A = 1,
B = A * 2
}
//在编译阶段会被删除
//常量枚举不允许包含计算成员
const enum Directions {
Up,
Down,
Left,
Right
}
let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right]
//生成后的代码
var directions = [0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */];
外部枚举
//外部枚举用来描述已经存在的枚举类型的形状。
declare enum Enum {
A = 1,
B,
C = 2
}
在正常的枚举里,没有初始化方法的成员被当成常数成员。 对于非常数的外部枚举而言,没有初始化方法时被当做需要经过计算的。