TypeScript条件类型区分泛型联合类型:报错原因与解决
TypeScript条件类型约束报错问题解析
代码示例
type A = {a: unknown} type TakesA<T extends A> = unknown type B = { b: unknown } type TakesB<T extends B> = unknown type AB = A | B type TakesAB<T extends AB> = T extends A ? TakesA<T> : TakesB<T>
报错信息
Type 'T' does not satisfy the constraint 'B'. Type 'AB' is not assignable to type 'B'
问题
按预期,条件类型的else分支应该能把T收窄为B类型,为什么会出现这个错误?该怎么解决?
报错原因
TypeScript泛型上下文里的条件类型,没办法直接修改泛型参数本身的约束。这里T的顶层约束是AB(也就是A | B),即便你写了T extends A ? ... : ...,else分支里的T依然被编译器视为整个AB联合类型,而非自动收窄后的B。
因为泛型要兼容所有可能的输入(也就是A或B),编译器不会因为条件判断就改变T的原始约束,而AB显然不能赋值给B,所以传给要求T extends B的TakesB时就会报错。
解决方法
方法1:用类型断言明确收窄类型
直接告诉编译器,else分支里的T一定是B类型,绕过约束检查:
type TakesAB<T extends AB> = T extends A ? TakesA<T> : TakesB<T as B>
或者通过交叉类型强化类型:
type TakesAB<T extends AB> = T extends A ? TakesA<T> : TakesB<T & B>
方法2:利用分布式条件类型让编译器自动处理
把条件类型拆分成两次判断,借助TypeScript的分布式条件类型特性,让编译器对联合类型的每个成员单独做类型检查,这样就能自动识别分支里的类型约束:
type TakesAB<T extends AB> = T extends A ? TakesA<T> : T extends B ? TakesB<T> : never;
方法3:放宽TakesB的约束(按需使用)
如果业务场景允许,可以调整TakesB的类型约束,让它兼容AB类型:
type TakesB<T extends AB & {b: unknown}> = unknown type TakesAB<T extends AB> = T extends A ? TakesA<T> : TakesB<T>
内容的提问来源于stack exchange,提问作者Jonan
相关产品推荐
相关产品推荐

