You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript类型转换中如何保留联合类型避免被条件类型分发解构

问题场景

现有如下类型定义:

type Test = {
  checked: boolean;
  selection: 'female' | 'male'
}

需要将其转换为所有非对象属性值包裹为Record<string, 原属性类型>的结构,目标类型如下:

type Test = {
  checked: Record<string, boolean>;
  selection: Record<string, 'female' | 'male'>
}

最初编写的泛型转换逻辑如下:

type NestedTest<T> = T extends object
  ? { [P in keyof T]: NestedTest<T[P]> }
  : Record<string, T>;

执行type Test2 = NestedTest<Test>;后得到的结果不符合预期,原联合类型被拆分:

type Test2 = {
    checked: Record<string, false> | Record<string, true>;
    selection: Record<string, "female"> | Record<string, "male">;
}
问题原因

该现象由TypeScript条件类型的分配式特性导致:

  • 当条件类型的泛型参数是未被包裹的裸类型参数时,若传入联合类型,TypeScript会将联合类型拆分为单个独立成员,逐个代入条件类型逻辑计算,最终将所有计算结果合并为新的联合类型返回。
  • 原代码中T extends object属于裸类型参数的条件判断:
    • 传入boolean(本质是true | false联合类型)时,会分别计算true和false两个分支,最终得到Record<string, true> | Record<string, false>
    • 传入'female' | 'male'联合类型时,会分别计算两个字面量类型分支,最终得到Record<string, 'female'> | Record<string, 'male'>
修复方案

关闭条件类型的分配特性即可,只需要将条件判断的两侧类型都用元组包裹,阻止TypeScript拆分联合类型:

type NestedTest<T> = [T] extends [object]
  ? { [P in keyof T]: NestedTest<T[P]> }
  : Record<string, T>;

使用修改后的泛型转换Test类型,即可得到预期结果:

type Test2 = NestedTest<Test>;
// 输出结果:
// type Test2 = {
//   checked: Record<string, boolean>;
//   selection: Record<string, "female" | "male">;
// }

内容的提问来源于stack exchange,提问作者ttquang1063750

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 13:48:13