为什么TypeScript中对象的类型会提前解析为联合类型的单侧分支
类型推导结果的核心原因
前置推导前提
该场景下的推导结果,是TypeScript静态控制流分析(类型收窄)机制的标准表现,完全符合语言规范的推导规则:
- 示例中的
Foo、Bar两个接口属于典型的可辨识联合类型,二者都带有字面量类型的kind判别属性:Foo的kind为固定字面量'foo',Bar的kind为固定字面量'bar' - 进入对应代码行面前,
obj的初始静态类型为Foo | Bar
第18行位置的收窄逻辑
当代码进入if (obj.kind !== 'bar')判断的真分支块内部时,TypeScript会自动对obj执行反向类型收窄。收窄的计算规则为:遍历联合类型的所有成员,剔除所有不满足当前分支判断条件的类型,仅将满足条件的类型作为当前位置的可能类型集合:
- 遍历到
Bar类型时,由于Bar的kind是固定字面量'bar',天生满足obj.kind === 'bar',与当前分支“kind不等于'bar'”的条件完全冲突,会被从可能的类型集合中完全剔除 - 遍历到
Foo类型时,由于Foo的kind是固定字面量'foo',天生满足obj.kind !== 'bar'的分支条件,会被保留在可能的类型集合中
经过上述计算,分支块内部obj的可能类型集合就只剩下Foo,并不会保留初始的Foo | Bar联合类型,这也是观测到“第18行obj已经被解析为Foo类型”的直接原因。
第19行obj被推导为never的原因
在上述已经被收窄为Foo的类型基础上,代码继续执行obj.kind === 'bar'的判断时,TypeScript会再次执行相同的收窄计算:
- 当前
obj的静态类型为Foo,其kind属性是固定的'foo'字面量,从静态类型层面就永远不可能满足kind === 'bar'的判断条件 - 满足该分支判断条件的可能类型集合为空,类型系统中空集合对应的类型即为
never。
常见认知误区
对该推导结果的困惑,大多来自对机制的认知偏差,核心是混淆了编译期静态类型推导与运行时动态判断的边界:TypeScript的类型收窄不会等待代码实际运行后再判定类型,所有推导都基于编译期已知的类型信息完成,只要从静态类型层面能推导出某个分支永远不可能被触发,对应位置的变量类型就会被标记为never。
内容的提问来源于stack exchange,提问作者Cory Harper
相关产品推荐
相关产品推荐

