递归类型中分布式联合未按预期工作的问题排查
为什么
[T] extends [string]的非分布式条件类型未生效? 问题的核心在于泛型类型的分布式展开优先级高于内部的非分布式条件判断。
当你调用TRecursiveType<"baggins" | "underhill">时,由于泛型定义中第一个条件是T extends Record<string, unknown>——这里的T是裸类型参数(没有被元组、对象等包裹),TypeScript会自动触发分布式条件类型逻辑:将联合类型的每个成员单独传入泛型,再将结果合并为联合类型。
也就是说,TRecursiveType<"baggins" | "underhill">会被拆解为:TRecursiveType<"baggins"> | TRecursiveType<"underhill">
每个单独的字符串类型进入[T] extends [string]分支后,都会返回对应的单类型数组,最终合并成"baggins"[] | "underhill"[],这就是你看到的结果。
解决方案
要阻止这种分布式展开,需要确保泛型定义中所有涉及T的条件判断都使用非裸类型参数。只需要把第一个条件的T extends Record<string, unknown>改为[T] extends [Record<string, unknown>],让整个泛型的判断逻辑从一开始就不触发分布式展开:
type TRecursiveType<T> = [T] extends [Record<string, unknown>] ? { [K in keyof T]: TRecursiveType<T[K]> } : [T] extends [string] ? Array<T> : never; type TExample = { frodo: "baggins" | "underhill", }; type TResult1 = TRecursiveType<TExample>; // 现在 TResult1 的类型是: // { frodo: ("baggins" | "underhill")[] }
这样修改后,当传入联合类型时,整个联合会被作为一个整体处理,而非拆分成分支,最终就能得到你期望的联合类型数组。
内容的提问来源于stack exchange,提问作者James Flight
相关产品推荐
相关产品推荐

