如何替换 TS 代码中的 Enum

204 阅读2分钟

前几天刷到了几次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 一起使用。

  1. const Status = { ... } as const as const 是 TypeScript 的“常量断言”,它告诉 TypeScript 将对象的每个属性值视为字面量类型(literal type),而不是宽泛类型(如 number 或 string)。
  • 没有 as const 时,Status.Success 的类型是 number。
  • 加了 as const 后,Status.Success 的类型是字面量 200。
  1. typeof 是 TypeScript 的类型查询操作符,用来获取变量的类型。typeof Status 的结果是:
{
  readonly Success: 200;
  readonly NotFound: 404;
  readonly ServerError: 500;
}
  1. keyof typeof Status
    keyof 操作符提取一个类型的键名,并生成它们的联合类型。所以:
keyof typeof Status = "Success" | "NotFound" | "ServerError"
  1. 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。
  1. type StatusValue = ...
  • 将这个推导结果赋值给类型别名 StatusValue