枚举是什么?

是用来组织一组有关系的数据的方式。

常见Demo如下:

1
2
3
4
5
6
enum Days {Sun, Mon, ...};
let sun:Days.Sun = 0;
enum Sex {male, female}

enum Age {0, 1, 2, ...}

Enum 默认和数字类型兼容

1
2
3
4
5
6
7
8
enum Days {
Sun,
Mon,
}
let sun: Days.Sun = '0';
^__ error 不能将类型“"0"”分配给类型“Days.Sun”。ts(2322)
let sun: Days.Sun = 0; // OK
let mon: Days.Mon = 2; // OK

**如何 修改 Enum 的值 **(Enum 的灵活)

  1. 修改默认初始值为某一整型,后续则 ++ 递增。且只有为nu

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    enum Days {
    Sun = 7,
    Mon, // 8
    }

    enum Days {
    Sun,
    Mon = 2, // 2
    Tue // 3
    }
  2. 任意修改,可以任意修改数值,但个人觉得没啥意义且有少许风险。

  3. 可以修改值为字符串类型

Enum字符型类型兼容

可以手动修改enum 的值为字符型,但是需要注意的是,字符类型无法推断,所以当修改为字符型时需要对每一个值添加类型。不然的话ts 会报错。

1
2
3
4
5
6
7
8
enum Days {
Sun = "3",
Mon = "4",
Tue,
// ^__ 枚举成员必须具有初始化表达式。ts(1061)
Wed,
// ^__ 枚举成员必须具有初始化表达式。ts(1061)
}

常量枚举

  • enum 的 const 声明

enum 可以加const 进行修饰,目的是为了编译后的性能提升。具体事例如下。

1
2
3
4
5
6
7
8
9
10
const enum Tristate {
False,
True,
Unknown
}

const lie = Tristate.False;

// 编译后结果
let lie = 0;

对于真实的JS代码来说,enum本身要么编译成对象, 要么编译无。对于 常量枚举Tristate.False 完全可以编译成 0(Tristate.False 的实际值) ,这个时候声明枚举的这一部分,完全可以拿掉。所以最终结果就是 *let lie = 0;*。- 这种编译方式称为内联模式。

当然这个是TS 默认实现,如果不想要这个移除,可以在tsconfig里进行配置 preserveConstEnums: false

1
2
3
4
5
"compilerOptions": {
{
"preserveConstEnums": false
}
}
  • enum 外部枚举(通过declare 声明) 编译后结果会擦除枚举的定义,谨慎使用
1
2
3
4
5
6
7
8
9
declare enum D {
Up,
}
let d : D = D.Up;
console.log("d", d);

---------- tsc 编译后 ----------
let d = D.Up;
console.log("d", d); // 会 error

Enum 的真实数值

对于实际成JS编译后的值,还是数字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let today : Days = Days.Sun; // today = 0

enum Tristate {
False,
True,
Unknown
}
// 实际编译后的结构
var Tristate;
(function(Tristate) {
Tristate[(Tristate['False'] = 0)] = 'False';
Tristate[(Tristate['True'] = 1)] = 'True';
Tristate[(Tristate['Unknown'] = 2)] = 'Unknown';
})(Tristate || (Tristate = {}));

Enum 的能力 双向映射

Enum 的值默认从 0 开始。

1
2
3
4
5
6
7
8
9
10
01  enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
02 console.log(Days["Sun"] === 0); // true
03 console.log(Days["Mon"] === 1); // true
04 console.log(Days["Tue"] === 2); // true
05 console.log(Days["Wed"] === 3); // true
06 console.log(Days["Sat"] === 6); // true
07 console.log(Days[0] === "Sun"); // true
08 console.log(Days[1] === "Mon"); // true
09 console.log(Days[2] === "Tue"); // true
10 console.log(Days[6] === "Sat"); // true

有静态方法的枚举

通过命名空间的形式给该枚举添加方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
enum Days {
Sun,
Mon,
Tue,
Wed,
}

namespace Days {
export function isWeekNumber(d: Days): string {
return Days[d];
}
}

console.log(Days.isWeekNumber(1));

开放式枚举