TypeScript 类型设计:让错误在编译期就暴露

把「什么都能传」的 interface 改成有约束的类型,重点讲可辨识联合与窄化。

什么时候用:项目里到处是 any 和可选字段,运行时才炸;类型写了但没拦住任何错误。

提示词(整段复制)

你是 TypeScript 类型设计专家。请重构下面这段类型与用法。

现有类型:
```ts
{{现有类型}}
```
实际可能出现的取值:{{取值情况}}
出现过的运行时错误:{{错误}}

请输出:
1. **问题诊断**:指出当前类型为什么拦不住那些错误(每条对应一个具体错误)。
2. **重构后的类型**:优先用可辨识联合(discriminated union)表达互斥状态,禁止用「一堆可选字段」表示状态机。
3. **窄化示例**:给出 2 段使用代码,展示错误写法在编译期报错、正确写法通过。
4. **边界处理**:外部输入(API/JSON)如何做一次校验转成内部类型,不要用 as 强转。
5. **迁移成本**:列出改完后会连带报错的调用点类型(不逐个改,只说明范围)。

约束:
- 不引入新依赖(除非说明为什么 zod/io-ts 是必要的)。
- 不用 any;确实未知用 unknown 并显式收窄。
- 不为了「看起来严谨」加无意义的泛型。

复制时把 {{变量}} 换成你自己的内容;变量名不要改,改了模型容易把它当普通文字。

要替换的变量

变量示例值
{{现有类型}}type Task = { id: string; status?: string; error?: string; result?: any }
{{取值情况}}status 只会是 pending / running / done / failed;done 必有 result,failed 必有 error
{{错误}}status 为 done 时 result 是 undefined,页面崩在 .map 上

实操建议

常见问题

一定要引入 zod 吗?

只在需要校验外部输入时。内部数据用 TS 类型就够,多一层运行时校验是有成本的。

迁移成本太大怎么办?

先只改「状态字段」这一处,它是错误密度最高的地方;其余用 any 暂时留着,别一次性重写。

配套工具