写给未来自己的 TypeScript 笔记
类型最有用的时刻,是它把原本藏在运行时的约定,变成了编辑器里清楚可见的边界。
本文为可替换的原创演示文章。
先描述状态,再编写分支
当一个请求同时使用 loading、error、data 三个变量时,很容易出现“正在加载且已经失败”这样的组合。把真实状态写成联合类型,可以减少需要记住的约定。
type Remote<T> =
| { status: 'loading' }
| { status: 'error'; message: string }
| { status: 'ready'; data: T };
界面只需根据 status 分支,进入 ready 后才允许访问 data。这个设计并没有消除复杂性,而是让复杂性集中在一个可以被检查的位置。
unknown 是一个有用的停顿
接口响应来自系统之外。即使给 fetch 的结果标注一个类型,也不会自动验证真实数据。面对外部输入,先使用 unknown,再通过校验得到业务类型,才能让类型承诺与运行时行为一致。
项目规模较小时,一个清晰的校验函数已经足够;表单与接口较多时,可以使用统一的 schema。关键是把验证放在边界,避免在每一个组件里重复猜测数据。
不急着把所有内容做成泛型
抽象应当消除已经存在的重复。为了某个假想的复用场景引入三层泛型,往往会让下一次修改变得困难。两个具体、可读的类型,有时比一个高度通用的工具类型更合适。
给未来自己的提醒是:类型设计的目标,是让意图更容易理解。读代码的人不该先解一道类型谜题,才能知道函数会返回什么。