枚举
用过别的开发语言的(比如 C#、Java 等)都应该接触过枚举值。在实际的开发中我们常常会遇到这样的情况。比如根据某条数据的状态来执行不同的操作,因此就会有如下的代码
if(status == 1){
....
}else if(status == 2){
....
}else{
....
}
但是这样的代码时很难知道数值 1、2 代表的是什么意思,别说不同的人来看了,就算同一个人,过段时间来看这个也不一定知道代表的意思。因此就有了枚举
,使用枚举我们可以定义一些带名字的常量。 使用枚举可以清晰地表达意图或创建一组有区别的用例。
enum STATUS {
success = 1,
error = 2,
other = 3
}
接下来我们可以修改上面的代码
if(status == STATUS.success){
....
}else if(status == STATUS.error){
...
}else {
....
}
这样两者相比,下面的明显比上面的在语义上更加容易读懂。
接下来我们来看看 TypeScript 中的枚举。TypeScript 支持数字的和基于字符串的枚举。
数字枚举
上面我们定义的就是一个数字枚举,我们为每一个值都进行了初始化,其实我们也可以如下那么来定义
enum STATUS {
success = 1,
error ,
other
}
这样定义,那么后面的值会在第一个定义的值基础上自增。即error = 2
,other = 3
,如果第一个值定义为 2,那么后面的就是从 2 开始自增的,如果我们在中间某个值进行了初始化,那么该值后面的值会在这个值的基础上进行自增
enum STATUS {
success,
error = 5,
other
}
// success: 0, error: 5, other: 6
字符串枚举
顾名思义,就是枚举的值是字符串,而字符串就没有自增了,因此所有的枚举必须进行初始赋值
enum STATUS {
success = 'success',
error = 'error',
other = 'other'
}
异构枚举
异构枚举就是同时使用了数字枚举和字符串枚举的
enum STATUS {
success = 1,
error = 'error',
other = 'other'
}
每个枚举成员都带有一个值,它可以是 常量或 计算出来的。
// 它是枚举的第一个成员且没有初始化器,这种情况下它被赋予值 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
}
反向映射
我们可以通过枚举的名字知道对应的值,也可以通过对应的值知道相应的名称,(这个在第一篇中已经有讲到了)
enum Color {red, green=3, blue}
编译后的
var Color
;(function (Color) {
Color[(Color["red"] = 0)] = "red"
Color[(Color["green"] = 3)] = "green"
Color[(Color["blue"] = 4)] = "blue"
console.log(Color) // { '0': 'red', '3': 'green', '4': 'blue', red: 0, green: 3, blue: 4 }
})(Color || (Color = {}))
var c = Color.green
console.log(c) // 3
console.log(Color[3]) // 'green'
const 枚举
常量枚举通过在枚举上使用 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 */]
TypeScript–类型推论
简单的类型推论,比如下面
let x = 2
这样就会推论 x 是一个数字类型的。这种推断发生在初始化变量和成员,设置默认参数值和决定函数返回值时。
当需要从几个表达式中推断类型时候,会使用这些表达式的类型来推断出一个最合适的通用类型。
let x = [0, 1, null]
为了推断x
的类型,我们必须考虑所有元素的类型。 这里有两种选择: number
和null
。 计算通用类型算法会考虑所有的候选类型,并给出一个兼容所有候选类型的类型。
当所有的候选类型共享相同的通用类型的时候,
// 没有使用通用类型
let zoo = [new Rhino(), new Elephant(), new Snake()] // (Rhino | Elephant | Snake)[]
// 使用了通用类型
let zoo: Animal[] = [new Rhino(), new Elephant(), new Snake()] // Animal[]