为什么TypeScript条件类型F<T,U>计算结果为false而非预期boolean?
类型推导结果为false的核心原因
先看复现代码:
type F<T extends { type: any }, U> = T["type"] extends U ? true : false; let f: F<{ type: string } | { type: number }, number>; // f的推导类型为false,而非预期的boolean
出现这个结果是两个TypeScript类型规则共同作用的:
- 第一,分布式条件类型有严格的触发前提:只有
extends关键字左侧的被检查类型是「完全裸露的泛型类型参数」(也就是没有被索引访问、数组、Promise等任何包装逻辑包裹的泛型参数本身)时,TS才会把传入的联合类型拆成单个成员逐个做条件判断,最后把所有判断结果联合成最终类型。
你写的T["type"] extends U里,extends左边是对T做索引访问的计算值,不是裸的T参数,所以分布式逻辑根本不会触发。 - 第二,非分布式场景下的
X extends Y判断逻辑是:X类型的所有可能值,是否都能合法赋值给Y类型。
这时候TS会先计算T为联合类型时T["type"]的结果:{type:string} | {type:number}的type属性类型是string | number。接下来判断string | number extends number是否成立:显然string | number里包含string类型的值,这类值不能赋值给number,因此条件判断整体不成立,直接走false分支,最终得到类型false。
如果要得到预期的boolean结果,需要改写F的定义,让extends左侧是裸泛型T,触发分布式逻辑,参考写法:
type F<T extends { type: any }, U> = T extends { type: U } ? true : false; let f: F<{ type: string } | { type: number }, number>; // 此时f的类型为false | true 即 boolean
这个写法里,TS会把传入的联合类型拆成两个分支单独判断:{type:string}匹配失败返回false,{type:number}匹配成功返回true,两个结果联合后就是boolean。
内容的提问来源于stack exchange,提问作者runlong
相关产品推荐
相关产品推荐

