前几天刷到了几次TypeScript官方不推荐使用Enum的消息,为了避免以后可能出现的不兼容问题,想把现有代码中的Enum替换掉。
这篇文章介绍了不推荐的原因、并介绍了几种替换方式,个人挑出其中推荐的做示例。
之前的代码:
enum Status {
Success = 200,
NotFound = 404,
ServerError = 500
}
function handleResponse(status: Status) {
console.log(`Status: ${status}`);
}
handleResponse(Status.Success); // output: 200
使用对象加as const的方式替换:
const Status = {
Success: 200,
NotFound: 404,
ServerError: 500
} as const;
type StatusValue = typeof Status[keyof typeof Status];
function handleResponse(status: StatusValue) {
console.log(`Status: ${status}`);
}
handleResponse(Status.Success); // output: 200
这种改动是比较小的,业务代码中枚举的引用不用改变,需要把方法参数的类型声明改为type形式。
之前的Enum会在编译为js时生成额外的运行时代码,使用as const的方式则避免了这种情况,同时保留了TS的类型检查
TS渣渣的我还特意问了下 type StatusValue = typeof Status[keyof typeof Status];这段代码的含义,以下是AI的回复:
这是一种常见的类型推导模式,用于从一个对象的值中提取联合类型。这种写法结合了 typeof 操作符和 keyof 操作符,通常与 as const 一起使用。
- const Status = { ... } as const as const 是 TypeScript 的“常量断言”,它告诉 TypeScript 将对象的每个属性值视为字面量类型(literal type),而不是宽泛类型(如 number 或 string)。
- 没有 as const 时,Status.Success 的类型是 number。
- 加了 as const 后,Status.Success 的类型是字面量 200。
- typeof 是 TypeScript 的类型查询操作符,用来获取变量的类型。typeof Status 的结果是:
{
readonly Success: 200;
readonly NotFound: 404;
readonly ServerError: 500;
}
- keyof typeof Status
keyof 操作符提取一个类型的键名,并生成它们的联合类型。所以:
keyof typeof Status = "Success" | "NotFound" | "ServerError"
- typeof Status[keyof typeof Status]
-
[] 是索引访问类型,用来从对象类型中获取指定键对应的值的类型。
-
这里,keyof typeof Status 是 "Success" | "NotFound" | "ServerError",所以:
typeof Status["Success" | "NotFound" | "ServerError"]
-
这等价于取出所有键的值的类型:
- typeof Status["Success"] 是 200。
- typeof Status["NotFound"] 是 404。
- typeof Status["ServerError"] 是 500。
- type StatusValue = ...
- 将这个推导结果赋值给类型别名 StatusValue