告别魔法数字

在以往的开发中往往会出现类似以下的代码

if(status === 1) {
   // do something
} else if(status === 2) {
   // do something
} else if (status === 3) {
  // ...
}

上面代码中的 123就是所谓的魔法数字,即没有注释的情况下我们很难知道 1,2,3 代表的到底是什么 status。

常量对象

在 javascript 中,我们可以将这些数字维护在一个常量对象中

const STATUS = {
  ERROR: 1,
  NORMAL: 2,
  SUCCESS: 3
}

使用时就可以使用 STATUS.ERROR 来替换掉 1。

这样可以很清晰就分清楚 1,2,3 这些数值对应的是什么含义。同时如果将来 ERROR 不再是 1,我们也只需要维护 STATUS 即可。

Enums

基本使用

而在 TypeScript 中,我们则可以使用枚举类型来维护这些数值。

enum STATUS {
  ERROR = 1,
  NORMAL,
  SUCCESS
}

使用时同样是 STATUS.ERROR 替换掉 1 即可。

关于 enums 的使用文档里描述的已经很清楚,这里不再赘述。

反向映射

值得一提的是 enums 提供了常量对象不具备的反向映射(value->name )。

const STATUS = {
  ERROR: 1,
  NORMAL: 2,
  SUCCESS: 3
}
// 输出:"ERROR"
STATUS[1]

这是因为 ts 将上述的 enums 编译成以下代码

var STATUS;
(function (STATUS) {
  STATUS[STATUS["ERROR"] = 1] = "ERROR";
  STATUS[STATUS["NORMAL"] = 2] = "NORMAL";
  STATUS[STATUS["SUCCESS"] = 3] = "SUCCESS";
})(STATUS || (STATUS = {}));

⚠️ 但如果是字符串枚举成员则不会生成反向映射。

enum STATUS {
  ERROR = "1",
  NORMAL = "2",
  SUCCESS = "3"
}
// 编译后
var STATUS;
(function (STATUS) {
  STATUS["ERROR2"] = "1";
  STATUS["NORMAL"] = "2";
  sSTATUS["SUCCESS"] = "3";
})(STATUS || (STATUS = {}));

并且对于重复定义的枚举类型,将会合并成员:

enum STATUS {
  ERROR = 1,
}

enum STATUS {
  NORMAL = 2,
}
// 等效于
enum STATUS {
  ERROR = 1,
  NORMAL = 2,
}

const 枚举

关于枚举,还有一种不是常见的写法

const enum STATUS {
  ERROR = 1,
}

即声明前有个关键字 const。

与常规枚举不同的地方在于

  1. const 枚举不会编译出额外的代码
const enum STATUS {
  ERROR = 1,
}
console.log(STATUS.ERROR)

// 最终的编译出的代码不包含 STATUS
console.log(1 /* ERROR */);
  1. 也正因为编译阶段就会确定下枚举的成员,const 枚举不可以包含计算成员
const geterror = () => 3

const enum STATUS {
  // In 'const' enum declarations member initializer must be constant expression.
  ERROR = geterror()
}