TypeScript Enum
· 11 min read
枚举(Enum)类型经常被用于取值在一定范围内的场景,比如一周只能有七天,角色权限设计等。枚举类型变量使用enum
字段来定义,枚举成员的值可以是数字或者字符串,并且枚举成员是只读的。
枚举按照类型划分,主要分为以下三种:
作为变量
数字枚举
自动递增
enum Days {
Sun,
Mon,
Tue,
Wed,
Thu,
Fri,
Sat,
}
上述定义了一个简单的数字枚举,对于没有初始化的数字枚举类型来说,第一个枚举成员会被赋值为0
,后面的成员值为其上一个枚举成员的值加1
。
修改上面的语句为:
enum Days {
Sun = 7,
Mon = 1,
Tue,
Wed,
Thu,
Fri,
Sat,
}
console.log(Days['Sun']); // 7
console.log(Days['Mon']); // 1
console.log(Days['Tue']); // 2
console.log(Days['Sat']); // 6
由例子的结果可以看出,未手动赋值的枚举成员会接着上一个枚举成员递增。
enum Days {
Sun = 3,
Mon = 1,
Tue,
Wed,
Thu,
Fri,
Sat,
}
console.log(Days['Sun'] === 3); // true
console.log(Days['Wed'] === 3); // true
console.log(Days[3] === 'Sun'); // false
console.log(Days[3] === 'Wed'); // true
通过上面的代码可以看出,当手动赋值的枚举成员数字较小时,可能会被后面成员值覆盖,此时通过值只能找到后面的枚举成员。
caution
当枚举成员较多时,如果对枚举成员赋值较小,很可能会被后面的枚举成员值覆盖。
反向映射
正向映射是指由key
求出value
的过程,而反向映射是指由value
求出key
的过程。数字枚举除了具有上述功能外,还具有反向映射功能,如下所示:
enum Days {
Sun,
Mon,
Tue,
Wed,
Thu,
Fri,
Sat,
}
console.log(Days['Sun']); //(1)
console.log(Days[Days['Sun']]); //(2)
console.log(Days[0]); //(3)
运行结果为:
0
Sun
Sun
由上面的例子可以看出,语句(1)中由key
值'Sun'
求出属性值0
属于正向映射,而(2)中由key
值Days['Sun']
求出属性值'Sun'
属于反向映射,其中 Days['Sun']
===0
。
是不是很不解为什么数字枚举可以反向映射?其实这和数字枚举的内部实现有关。上面的式子可以编译为:
var Days;
(function (Days) {
Days[(Days['Sun'] = 0)] = 'Sun';
Days[(Days['Mon'] = 1)] = 'Mon';
Days[(Days['Tue'] = 2)] = 'Tue';
Days[(Days['Wed'] = 3)] = 'Wed';
Days[(Days['Thu'] = 4)] = 'Thu';
Days[(Days['Fri'] = 5)] = 'Fri';
Days[(Days['Sat'] = 6)] = 'Sat';
})(Days || (Days = {}));
console.log(Days); // {0: "Sun", 1: "Mon", 2: "Tue", 3: "Wed", 4: "Thu", 5: "Fri", 6: "Sat", Sun: 0, Mon: 1, Tue: 2, Wed: 3, Thu: 4, Fri: 5, Sat: 6}
由上面编译的结果可知,对于枚举中的Days
是由JS
中的对象实现的。Days
的枚举成员和对应的值分别作为 Days 的key: value
,然后又作为value: key
存到Days
对象中,实现了反向映射功能。
字符串枚举
字符串枚举要求每一个枚举成员的值都必须是字符串,或者是对其它字符串枚举成员的引用。
enum Direction {
Up = 'UP',
Down = 'DOWN',
Left = 'LEFT',
Right = 'RIGHT',
}
编译为:
var Direction;
(function (Direction) {
Direction['Up'] = 'UP';
Direction['Down'] = 'DOWN';
Direction['Left'] = 'LEFT';
Direction['Right'] = 'RIGHT';
})(Direction || (Direction = {}));
与数字枚举相比,字符串枚举没有反向映射,但是字符串枚举可以提供一个运行时更有意义的值。