TypeScript:联合类型在索引签名中分布式条件类型失效问题及解决方法咨询
解决TypeScript索引签名中分布式条件类型失效的问题
你碰到的这个问题其实是TypeScript分布式条件类型的一个常见"坑"——只有当条件类型的左侧是「裸泛型参数」时,才会触发分布式展开,而在映射类型的索引签名里直接写L[K] extends ...时,L[K]并不是一个裸泛型参数,而是一个已经被解析的联合类型,所以不会自动拆分处理。
解决方案:用辅助泛型手动触发分布式
最直观的解决方式是把条件逻辑抽成一个单独的泛型,让联合类型参数以裸参数的形式传入,从而触发分布式行为:
// 定义一个辅助泛型,这里的T是裸参数,会触发分布式 type DistributeUndefinedCheck<T> = T extends undefined ? "here" : "there"; // 在映射类型中使用这个辅助泛型 type test<L extends { [index: string]: unknown }> = { [K in keyof L]: DistributeUndefinedCheck<L[K]>; }; // 现在结果符合预期了 type e = test<{a: boolean | undefined}>; // {a: "here" | "there"}
为什么原来的写法不生效?
原来的代码里,L[K] extends undefined ? "here" : "there"是直接对boolean | undefined这个整体做条件判断:
boolean | undefined extends undefined这个判断是不成立的(因为boolean并不继承自undefined)- 所以条件分支直接走到
"there",没有把联合类型拆分成boolean和undefined分别处理
而当我们把L[K]传入DistributeUndefinedCheck时,T是一个裸的泛型参数,TypeScript会自动把联合类型boolean | undefined拆成两个独立的类型,分别代入条件判断:
boolean extends undefined→ 不成立,返回"there"undefined extends undefined→ 成立,返回"here"
最后把两个结果合并成联合类型"here" | "there",就得到了预期的结果。
另一种简化写法(无需额外泛型)
如果你不想单独定义辅助泛型,也可以用infer来构造一个裸参数:
type test<L extends { [index: string]: unknown }> = { [K in keyof L]: (L[K] extends infer T ? T : never) extends undefined ? "here" : "there"; };
这里通过infer T把L[K]转换成了一个裸泛型参数T,同样能触发分布式展开,效果和第一种方法一致。
内容的提问来源于stack exchange,提问作者Acid Coder
相关产品推荐
相关产品推荐

