创建了一个 “重学TypeScript” 的微信群,想加群的小伙伴,加我微信"semlinker",备注重学TS。
本文是 ”重学TS“ 系列,第 26 篇文章,感谢您的阅读!
一、基础知识
在 JavaScript 中布尔类型的变量含有有限范围的值,即 true 和 false。而在 TypeScript 中使用枚举,你也可以自定义相似的类型。
1.1 数字枚举
这是一个枚举的简单示例:
enum NoYes {
No,
Yes,
}
No 和 Yes 被称为枚举 NoYes 的成员。与对象字面量一样,尾随逗号是被允许的。对于 NoYes 枚举我们能够轻易的访问它的成员,比如:
function toChinese(value: NoYes) {
switch (value) {
case NoYes.No:
return '否';
case NoYes.Yes:
return '是';
}
}
assert.equal(toChinese(NoYes.No), '否');
assert.equal(toChinese(NoYes.Yes), '是');
1.1.1 枚举成员值
每个枚举成员都有一个 name 和一个 value。数字枚举成员值的默认类型是 number 类型。也就是说,每个成员的值都是一个数字:
enum NoYes {
No,
Yes,
}
assert.equal(NoYes.No, 0);
assert.equal(NoYes.Yes, 1);
除了让 TypeScript 为我们指定枚举成员的值之外,我们还可以手动赋值:
enum NoYes {
No = 0,
Yes = 1,
}
这种通过等号的显式赋值称为 initializer。如果枚举中某个成员的值使用显式方式赋值,但后续成员未显示赋值, TypeScript 会基于当前成员的值加 1 作为后续成员的值,比如以下 Enum 枚举中的成员 C:
enum Enum {
A,
B,
C = 4,
D,
E = 8,
F,
}
assert.deepEqual(
[Enum.A, Enum.B, Enum.C, Enum.D, Enum.E, Enum.F],
[0, 1, 4, 5, 8, 9]
);
1.2 枚举成员名称的转换
常量的命名有几种约定:
传统上,JavaScript 使用全大写的名称,这是它从 Java 和 C 继承的约定: Number.MAX_VALUE;
众所周知的 Symbol 用驼峰式表示,并以小写字母开头,因为它们与属性名称相关: Symbol.asyncIterator;
TypeScript 手册使用以大写字母开头的驼峰式名称。这是标准的 TypeScript 风格,我们将其用于 NoYes 枚举。
1.3 引用枚举成员名称
与 JavaScript 对象类似,我们可以使用方括号来引用包含非法字符的枚举成员:
enum HttpRequestField {
'Accept',
'Accept-Charset',
'Accept-Datetime',
'Accept-Encoding',
'Accept-Language',
}
assert.equal(HttpRequestField['Accept-Charset'], 1);
1.4 基于字符串的枚举
除了数字枚举,我们还可以使用字符串作为枚举成员值:
enum NoYes {
No = 'No',
Yes = 'Yes',
}
assert.equal(NoYes.No, 'No');
assert.equal(NoYes.Yes, 'Yes');
对于纯字符串枚举,我们不能省略任何初始化程序。
1.5 异构枚举
最后一种枚举称为异构枚举。异构枚举的成员值是数字和字符串的混合:
enum Enum {
A,
B,
C = 'C',
D = 'D',
E = 8,
F,
}
assert.deepEqual(
[Enum.A, Enum.B, Enum.C, Enum.D, Enum.E, Enum.F],
[0, 1, 'C', 'D', 8, 9]
);
请注意,前面提到的规则也适用于此:如果先前的成员值为数字,则我们能省略初始化程序。异构枚举由于其应用较少而很少使用。
目前 TypeScript 只支持将数字和字符串作为枚举成员值。不允许使用其他值,比如 symbols。
二、指定枚举成员值
TypeScript 区分了三种指定枚举成员值的方式:
使用字面量进行初始化:
隐式指定;
通过数字字面量或字符串字面量。
常量枚举成员通过可在编译时计算其结果的表达式初始化。
计算的枚举成员可通过任意表达式初始化。
2.1 字面量枚举成员
如果枚举只有字面量成员,我们可以将这些成员用作类型(类似于数字字面量可以用作类型的方式):
enum NoYes {
No = 'No',
Yes = 'Yes',
}
function func(x: NoYes.No) {
return x;
}
func(NoYes.No); // OK
//@ts-ignore: Argument of type '"No"' is not assignable to
// parameter of type 'NoYes.No'.
func('No');
//@ts-ignore: Argument of type 'NoYes.Yes' is not assignable to
// parameter of type 'NoYes.No'.
func(NoYes.Yes)