distributive conditional types是否为TS预期行为?常见使用场景有哪些?
关于分布式条件类型的默认行为
分布式条件类型(distributive conditional types)确实是TypeScript类型系统的默认预期行为,触发条件是你使用的条件类型入参为裸类型参数(没有被数组、元组等其他类型包装)且入参是联合类型,此时TS会自动把联合类型的每个成员单独代入条件逻辑计算,最后把所有结果合并为新的联合类型返回。
如果不需要这个分布式特性,按照官方说明的方式,把extends两侧的类型都用方括号包裹即可关闭,比如:
原本的分布式写法:T extends U ? X : Y
关闭分布式的写法:[T] extends [U] ? X : Y
常见实际使用场景
- 实现联合类型的过滤逻辑:TS内置的
Exclude、Extract、NonNullable等工具类型都是基于这个特性实现的。比如Exclude<T, U>的核心实现就是T extends U ? never : T,当T是'a'|'b'|'c'、U是'a'时,分布式特性会分别对三个成员做判断,最终排除匹配到的'a',得到'b'|'c'的结果。 - 批量转换联合类型的每个成员:比如你需要把联合类型的每个成员都包装成Promise类型,就可以写
type DistributePromise<T> = T extends unknown ? Promise<T> : never,当传入string | number时,会得到Promise<string> | Promise<number>,而不是不符合预期的Promise<string | number>。 - 筛选联合类型中的特定类型:比如你需要从混合了多种类型的联合类型里提取出所有函数类型,就可以写
type FunctionFilter<T> = T extends (...args: any[]) => any ? T : never,传入number | string | (() => void) | ((a: number) => boolean)时,会自动筛选出两个函数类型组成的联合。 - 简化复杂联合类型的分支处理:对于多分支的复杂条件判断,分布式特性可以避免你手动遍历联合类型的每个成员,大幅简化类型代码的写法,也更符合日常开发的直觉。
内容的提问来源于stack exchange,提问作者lei li
相关产品推荐
相关产品推荐

