TypeScript映射泛型为何无条件也会触发分布式特性?
TypeScript泛型映射的分发行为差异解析
很多人知道TypeScript的条件类型会触发泛型分发,但会疑惑为什么无嵌套条件的泛型映射类型也会出现分发行为,看下面的示例:
type Box<U> = { [K in keyof U]: [U[K]] }; // 普通的映射泛型 type Objects = {a: 1, b: 2} | {a: 3, c: 4}; type Distributed = Box<Objects>; type NotDistributed = { [K in keyof Objects]: [Objects[K]] }; // 逻辑和Box一致,但结果不同
两者生成的类型有明显差异:
// 触发分发的结果 type Distributed = { a: [1]; b: [2]; } | { a: [3]; c: [4]; } // 未触发分发的结果 type NotDistributed = { a: [1 | 3]; }
差异原因解析
核心区别在于是否经过泛型参数的实例化流程:
- 当调用
Box<Objects>时,泛型参数U接收的是联合类型Objects。TypeScript对泛型类型的实例化有个默认规则:如果泛型参数是联合类型,会将联合的每个成员单独代入泛型内部逻辑,再把处理后的结果重新组合成联合类型——这个分发行为不仅适用于条件类型,同样覆盖泛型内部的映射、索引访问等操作。 - 而直接写
{ [K in keyof Objects]: [Objects[K]] }时,没有通过泛型参数传递,TypeScript会先对联合类型Objects整体处理:先提取所有成员的共有键(也就是"a"),再取该键对应的联合类型值(1 | 3)进行映射,自然不会触发分发。
简单总结:泛型参数的联合类型会触发自动分发,直接对联合类型做映射则是先合并处理共有部分,两者的执行逻辑顺序不同导致了结果差异。
内容的提问来源于stack exchange,提问作者cipak
相关产品推荐
相关产品推荐

