TypeScript条件类型中联合类型被转为never的问题求助
TypeScript条件类型处理联合类型时参数变为never的问题解决
问题复现
定义了如下条件类型:
type SimpleTest<U> = U extends {something: string} ? () => void : (a: U) => U
当传入联合类型'test' | 'rest'时,出现不符合预期的类型错误:
function test(a: SimpleTest<'test' | 'rest'>) { a('test'); // 错误:TS2345: 类型“string”的参数不能赋给类型“never”的参数。 }
实际推导得到的类型是(a: never) => ("test" | "rest"),但期望的是(a: "test" | "rest") => ("test" | "rest")。
问题原因
这是TypeScript分布式条件类型的特性导致的:当泛型参数是「裸类型」(未被包裹在数组、对象等容器类型中)时,条件类型会自动遍历联合类型的每个成员,分别应用条件判断后再合并结果。
对SimpleTest<'test' | 'rest'>来说,实际执行逻辑是:
- 拆分联合类型为
'test'和'rest'两个独立成员 - 对每个成员应用条件:两者都不满足
{something: string},因此得到两个函数类型:(a: 'test') => 'test'和(a: 'rest') => 'rest' - 合并这两个函数类型:函数参数是逆变的,交叉后
'test' & 'rest'等于never;返回值是协变的,合并后是'test' | 'rest',最终就得到了(a: never) => ("test" | "rest")。
解决方案
要阻止条件类型的自动分发,只需将泛型参数U包裹在一个非裸类型中(比如元组、对象),让条件判断针对整个联合类型而非单个成员:
type SimpleTest<U> = [U] extends [{something: string}] ? () => void : (a: U) => U
修改后,SimpleTest<'test' | 'rest'>会直接将整个联合类型'test' | 'rest'与{something: string}做判断,显然不满足条件,因此会返回(a: 'test' | 'rest') => 'test' | 'rest',此时调用a('test')就不会再报错。
内容的提问来源于stack exchange,提问作者Pavel Karpovich
相关产品推荐
相关产品推荐

