DevCN
菜单
全部文章快讯开发科技深度热点

TypeScript 联合类型:让任务加载状态与数据保持一致

把等待、成功和失败表示成可辨识联合,按状态访问对应字段,并用 never 检查遗漏分支,减少互相矛盾的布尔状态。


本节目标

把等待、成功和失败表示成可辨识联合,按状态访问对应字段,并用 never 检查遗漏分支,减少互相矛盾的布尔状态。

环境与运行方法

安装 Node.js 与项目内 TypeScript 编译器。保存为 lesson.ts,执行 npx tsc lesson.ts --strict --target ES2020 --module commonjs --outDir dist,再运行 node dist/lesson.js。编译成功不等于外部数据已经校验。

核心思路

分别维护 loading、error、data 容易构造同时成功又失败的组合。将每种状态与它携带的数据放在同一个联合成员里,可以让不合法组合更难出现。

完整示例

type LoadState =
  | {kind: "loading"}
  | {kind: "success"; title: string}
  | {kind: "error"; message: string};
function label(state: LoadState): string {
  switch (state.kind) {
    case "loading": return "loading";
    case "success": return state.title;
    case "error": return "error=" + state.message;
    default: {
      const unreachable: never = state;
      return unreachable;
    }
  }
}
for (const state of [
  {kind: "loading"},
  {kind: "success", title: "review"},
  {kind: "error", message: "offline"}
] as LoadState[]) console.log(label(state));

预期输出

loading
review
error=offline

逐步理解

switch 根据 kind 区分分支,成功分支才有 title,失败分支才有 message。default 中将 state 赋给 never,用于在新增成员却忘记处理时产生编译错误。

本例数组是内部声明的数据。真实网络响应仍不能只靠 as LoadState[] 来验证,应按上一节思路校验字段再构造状态。状态类型可以保护程序内的数据流,但不会代替服务端协议检查。

常见问题与边界

  • 不要为了避开遗漏分支错误把 never 改成 any。
  • 字段全部可选会削弱状态与数据之间的对应关系。
  • 类型之外仍要设计用户界面在失败后如何重试。

动手练习

增加 {kind:"empty"} 状态但暂不添加 switch 分支。

参考答案

严格编译应在 never 赋值处提示缺失处理。增加 case "empty" 返回提示后恢复通过,这就是编译期穷尽检查的用途。

下载推广海报

文章推广海报

《TypeScript 联合类型:让任务加载状态与数据保持一致》完整推广海报
DISCUSSION

文章回复

0 条公开回复
未登录回复需要审核后公开
还没有回复,欢迎参与讨论。