枚举
enum 类型是对 JavaScript 标准数据类型的一个补充(使用枚举类型可以为一组数值赋予友好的名字),枚举类型用于定义数值集合。
enum 成员
下面示例声明了一个 Enum 结构 Color,里面包含三个成员 Red、Green 和 Blue。第一个成员的值默认为整数 0,第二个为 1,第三个为 2,以此类推。
enum Color {
Red,
Green,
Blue,
}
let c: Color = Color.Green;
console.log(c); // Output: 1
可以手动的指定成员的数值,指定成员数值后的值依次递增。
enum Color {
Red,
Green = 5,
Blue,
Yellow,
Black,
White,
}
const c = Color.Red;
const c1 = Color.Blue;
console.log(c, c1); // Output: 0 6
如果手动指定的成员的值比它本身的索引小,那么就会出现和之前成员值相等的情况,下面Color类型的 Green 和 Blue 成员就出现了值相同的情况, 因为Green本身值为 1 ,而我们手动指定了 Blue 成员的值为 1,所以它们的值相同。
enum Color {
Red,
Green,
Blue = 1,
Yellow,
Black,
White,
}
const c = Color.Green;
const c1 = Color.Yellow;
console.log(c, c1); // Output: 1 2
console.log(Color.Green === Color.Blue); // Output true
可以为 enum 成员赋值任意数值,但不能是 bigint 和 boolean。
enum Mix {
Num = 1000,
Binary = 0x11111,
BinaryOperation = 4 >> 1,
UserName = "rinvay",
Flag = true, // error Type 'boolean' is not assignable to type 'number' as required for computed enum member values.
BigInt = 7n, // error Type 'bigint' is not assignable to type 'number' as required for computed enum member values.
}
同名 enum
同名的 enum 结构会自动合并。
enum Word {
A,
B,
}
enum Word {
C = 2,
D = 3,
}
console.log(Word.A, Word.B, Word.C, Word.D); // Output: 0 1 2 3
同名的 enum 内部成员不能重复,哪怕成员的数值是相同的,下面两个 Word 类型都存在成员 B ,就会报错。
enum Word {
A,
B,
}
enum Word {
B = 1, // error 标识符“B”重复。
C = 3,
}
console.log(Word.A, Word.B, Word.C);
在多个同名的 enum 枚举中,只有一个声明可以省略其第一个枚举元素的初始化表达式。
enum Word {
A,
B,
}
enum Word {
C, // error 在包含多个声明的枚举中,只有一个声明可以省略其第一个枚举元素的初始化表达式。
D,
}
enum Word {
A,
B,
}
enum Word {
C = 0, // ok
D,
}
enum 编译
enum 它既是一种类型,也是一个值。因为绝大多数 TypeScript 语法都是类型语法,编译后会全部去除,最终都会以 Js 语法呈现, enum 编译后会变成 JavaScript 对象,留在代码中。
enum Word {
A,
B,
C,
D,
}
上面的 TypeScript 代码最终会编译成下面的一个 JavaScript 对象,可以看到对象中不只有 A, B, C, D 属性。还有 0, 1, 2, 3 可以通过 Word[x] 取到 A, B, C, D 的值。
var Word;
(function (Word) {
Word[(Word["A"] = 0)] = "A";
Word[(Word["B"] = 1)] = "B";
Word[(Word["C"] = 2)] = "C";
Word[(Word["D"] = 3)] = "D";
})(Word || (Word = {}));
console.log(Word); // {0: 'A', 1: 'B', 2: 'C', 3: 'D', A: 0, B: 1, C: 2, D: 3}
enum 成员赋值字符串的时候 TypeScript 处理会有一些区别。
enum Word {
A,
B = 4 >> 1,
C = "2",
D = "rinvay",
}
编译后的 Word 对象中,成员赋值字符串的时候并不会生成以字符串为 key 的健值对。所以上面的 Word 类型并不能通过 Word['rinvay'] 取到值 D。
var Word;
(function (Word) {
Word[(Word["A"] = 0)] = "A";
Word[(Word["B"] = 2)] = "B";
Word["C"] = "2";
Word["D"] = "rinvay";
})(Word || (Word = {}));
console.log(Word); // {0: 'A', 2: 'B', A: 0, B: 2, C: '2', D: 'rinvay'}
keyof 运算符
keyof 运算符可以取出 enum 类型的所有成员名作为联合类型返回。
enum Bool {
No,
Yes,
}
type Flag = keyof typeof Bool;
const no: Flag = "No";
const yes: Flag = "Yes";
如果要返回 enum 所有的成员值,可以使用 in 运算符。
enum Bool {
No = "no",
Yes = "yes",
}
/**
* 等同
* type Flag = {
* no: string;
* yes: string;
* };
*/
type Flag = { [key in Bool]: string };
const flag: Flag = {
no: "0",
yes: "1",
};