TypeScript联合类型下typeof判断a为string时b仍报类型错误原因
核心原因
出现这个问题的本质是TypeScript的类型收窄不会追踪解构出来的独立变量之间的关联绑定:
- 你在参数位置直接把联合类型
Type的入参解构为a、b两个独立常量后,两个变量的类型推导是互相独立的,初始类型都为string | number。 - 当你写
typeof a === 'string'做判断时,TS确实会把当前代码块内的a类型收窄为string,但它不会同步关联收窄同作用域下的b——因为解构后b已经是和a无关的独立变量,TS默认不会消耗额外性能追踪这类跨变量的类型绑定关系,所以此时b的类型仍然是string | number,直接返回给标注为string类型的返回值自然会报类型不匹配错误。
你传入{a: 1, b: 'w/e'}时的报错是完全符合预期的:Type本身是两个对象类型的联合,只接受「a、b全为string」或「a、b全为number」两种结构,混合a、b类型的对象本来就不符合类型定义,这个报错也能证明TS并没有把Type错误解析为{a: string | number; b: string | number;}的平铺结构——如果是那样的话,混合类型的入参是不会触发报错的。
修复方案
最稳妥无副作用的修复方式是不要直接解构参数,保留对原入参对象的引用,通过属性访问的方式做判断,TS可以正确对联合类型的对象做判别式收窄:
type Type = { a: string; b: string; } | { a: number; b: number; }; const func = (obj: Type): string => { if (typeof obj.a === 'string') { // 此处TS会正确收窄obj为{a:string; b:string}分支,obj.b类型为string,无报错 return obj.b; } return 'w/e'; } // 混合类型入参仍然会正确报错,符合类型约束 // func({a: 1, b: 'w/e'});
如果你坚持要使用解构语法,也可以在收窄a的类型后,对b做手动类型断言,但这种方式安全性稍差,需要自行保证逻辑上b的类型和a是匹配的:
const func = ({a, b}: Type): string => { if (typeof a === 'string') { return b as string; } return 'w/e'; }
内容的提问来源于stack exchange,提问作者pkyriazo
相关产品推荐
相关产品推荐

