TypeScript中应该禁止使用enum

TypeScript 添加了一个 enum 的数据类型结构,但是这个数据类型在 JavaScript 中并不存在,在编译过程中会被转换成 Object。并且 enum 类型可以完全被 union 类型替代。 所以我们推荐使用 union 来代替 enum。接下来我们使用一个例子来解释下 enum 如何被替换成 union。

# enum 定义数据类型

我们来封装一个常见的 fetch 函数,使用 enum 定义的代码如下。

enum HTTPRequestMethod {
  GET = 'GET',
  POST = 'POST'
}

function fetchJSON(url: string, method: HTTPRequestMethod) {
  return fetch(url, { method }).then(response => response.json());
}
1
2
3
4
5
6
7
8

编译成 JS 代码如下:

'use strict';
var HTTPRequestMethod;
(function(HTTPRequestMethod) {
  HTTPRequestMethod['GET'] = 'GET';
  HTTPRequestMethod['POST'] = 'POST';
})(HTTPRequestMethod || (HTTPRequestMethod = {}));
function fetchJSON(url, method) {
  return fetch(url, { method }).then(response => response.json());
}
1
2
3
4
5
6
7
8
9

这样编译的 JS 代码,定义了 HTTPRequestMethod 对象,但并不是 const 常量,有被更改的可能性,非常不优雅。

# union 定义数据类型

const HTTPRequestMethod = {
  GET: 'GET',
  POST: 'POST'
} as const;

type ValuesOf<T> = T[keyof T];
type HTTPRequestMethodType = ValuesOf<typeof HTTPRequestMethod>;

function fetchJSON(url: string, method: HTTPRequestMethodType) {
  return fetch(url, { method }).then(response => response.json());
}
1
2
3
4
5
6
7
8
9
10
11

编译成 js 代码之后是:

'use strict';
const HTTPRequestMethod = {
  GET: 'GET',
  POST: 'POST'
};
function fetchJSON(url, method) {
  return fetch(url, { method }).then(response => response.json());
}
1
2
3
4
5
6
7
8

# 总结

对比 enum 和 union 定义生成的代码,我们能明显感受到 union 类型生成的代码更优雅。而且 enum 还有其他缺点,大家可以查看下参考链接。

# 参考

さようなら、TypeScript enum (opens new window)

Why it is not good to use enums? (opens new window)

Const Assertions in Literal Expressions in TypeScript (opens new window)