TypeScript中能否链式/嵌套使用模板字面量类型
问题原因
你最初的写法无法得到预期结果,核心原因是Second<First>直接传入了完整联合类型'a' | 'x':Second作为条件类型,接收到完整联合时会直接通过分布式计算返回'z' | 'q',后续模板字面量会对两侧的联合类型做全量笛卡尔积组合,最终得到'az' | 'aq' | 'xz' | 'xq',自然无法拦截aq这类错误值。
你之前实现的泛型版本其实已经摸到了正确逻辑——利用条件类型的分发特性逐个处理联合成员,只是需要手动传入泛型参数,实用性不足。
非泛型实现方案
可以直接在Both类型内部触发分布式条件类型,拆分First的每个成员单独计算拼接结果,不需要暴露任何泛型参数:
type First = 'a' | 'x' type Second<F extends First> = F extends 'a' ? 'z' : 'q' // 目标非泛型类型 type Both = First extends infer F extends First ? `${F}${Second<F>}` : never // 校验结果 const bothGood1: Both = 'az' // 校验通过 const bothGood2: Both = 'xq' // 校验通过 const bothBad1: Both = 'aq' // 抛出类型错误 const bothBad2: Both = 'xz' // 抛出类型错误
实现原理
First extends infer F extends First的写法会触发TypeScript的分布式条件类型特性:编译器会把联合类型First拆分为'a'、'x'两个独立类型,分别代入后续分支计算- 拆分后的单个成员
F传入Second<F>时,只会返回对应的单个匹配值:'a'对应'z','x'对应'q',不会返回联合类型 - 所有分支计算完成后,TypeScript会自动把结果联合为最终类型
'az' | 'xq'
这种模式可以直接扩展到更复杂的多段链式字面量组合场景,只要保持对前序联合的逐成员分发,再拼接对应位置的条件返回类型,就可以避免全量笛卡尔积的问题,精准生成符合条件映射关系的联合类型。
内容的提问来源于stack exchange,提问作者Sasgorilla
相关产品推荐
相关产品推荐

