TypeScript 类型体操的边界
2 分钟1 条评论
类型系统是 TypeScript 最好的礼物,也可能是最坏的诱惑。什么时候该用复杂的类型推导,什么时候该停下来,值得认真讨论。
类型体操真正值钱的场景#
抽公共库的时候,类型体操回报最高。一个经典的例子——把对象类型的值域取出来:
type Values<T> = T[keyof T]
const STATUS = {
idle: 'idle',
loading: 'loading',
done: 'done',
} as const
type Status = Values<typeof STATUS> // 'idle' | 'loading' | 'done'
这类推导的好处是单一事实来源:运行时对象和类型永远同步,没有第二处需要维护。
什么时候应该刹车#
遇到这几种信号,就该退回简单方案:
- 类型参数出现三层以上的条件嵌套,报错信息已经没人读得懂;
- 为了类型完备,运行时被塞进了只服务于类型的代码;
- 团队里超过一半的人无法修改这段类型。
类型是给人看的,不是给编译器写的诗。
务实的替代方案#
很多"高难推导"其实有平替:
- 代码生成:schema 生成类型,简单粗暴、永远准确;
- 声明合并 + 显式断言:把不确定性圈在一个有注释的小范围里;
- 测试兜底:用
expectTypeOf之类的工具把类型预期写成测试,复杂度被文档化。
我的判断标准#
一句话:库代码可以聪明,业务代码必须无趣。业务代码的读者是半年后的自己和刚入职的同事,无趣是一种美德。