TypeScript中的枚举类型定义方式的优劣对比

2,257 阅读1分钟

一、enum

直接通过enum定义:

enum Color{
    RED,
    GREEN,
    BLUE,
}
console.log(Color.RED)

编译成JavaScript的结果如下:

var Color;
(function (Color) {
    Color[Color["RED"] = 0] = "RED";
    Color[Color["GREEN"] = 1] = "GREEN";
    Color[Color["BLUE"] = 2] = "BLUE";
})(Color || (Color = {}));
console.log(Color.RED)

这种方式虽然是TypeScript提供的,但其实是比较不好的一种方式,因为如果枚举类型未赋值,或者是赋值了Number类型时,在编译完成后,引入了JavaScript中不存在的数据类型:双向Map,能够得到如下结果:

Color[0] // RED
Color.RED // 0
Color[1] // GREEN
Color.GREEN // 1
Color[2] // BLUE
Color.BLUE // 2

二、const enum

通过 const enum定义

const enum Color {
    RED,
    GREEN,
    BLUE
}
console.log(Color.RED)

编译结果如下:

console.log(0 /* RED */);

这种方式是在编译时将使用到枚举值的地方直接替换,最终不会编译出枚举的解构,因此在编译完成后的JavaScript代码中,会存在大量的魔术字符串(可能会对排查线上问题时造成一定的影响)。

三、const x = {} as const

使用as const将对象的属性设置为所有readonly

const Color = {
    RED: 0,
    GREEN: 1,
    BLUE: 2
} as const

编译成JavaScript的结果如下:

var Color = {
    RED: 0,
    GREEN: 1,
    BLUE: 2
};

这种方式是定义了一个对象,然后通过as const将Color中的每个属性都设置成readonly,且无副作用产生。

总结

在枚举类型为数字且不需要在Interface中使用时,建议使用方式三来定义,枚举类型为字符串时,可考虑方式一或者方式三;如需在Interface中使用,考虑方式一,同时约定不省略值(即key value)的写法,如有更好的方式或其他见解,欢迎讨论~