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

如何将TypeScript交叉类型的所有字段合并为单个对象类型?

如何在TypeScript中实现可展开的交叉类型合并工具?

在TypeScript中定义交叉类型(如type All = A & B & C & D)时,类型会显示为多个对象的交叉形式,可读性很差,排查TS错误时尤其麻烦。我自己写了个Merge泛型工具,但结果总是嵌套的Merge调用,没法直接展开成包含所有字段的单个对象类型。比如希望Merge<A,B>能直接生成{ foo: string; fizz: number },请问该怎么实现?

示例代码:

type A = { foo: string }
type B = { fizz: number }
type C = { bar: boolean }
type D = { buzz: null | string }

type All = A & B & C & D

尝试的Merge泛型:

type Merge<T, U> = {
    [P in (keyof T | keyof U)]: P extends keyof T
        ? T[P]
        : P extends keyof U
          ? U[P]
          : never;
}

解决方案

要实现能直接展开为单个对象的合并工具,需要处理递归合并逻辑,同时触发TypeScript自动展开最终的类型结构,具体实现如下:

1. 二元类型合并(支持自动展开)

先优化二元合并逻辑,确保合并后的类型不会以交叉形式显示:

// 先处理键覆盖,再通过映射类型触发展开
type MergeTwo<T, U> = Omit<T, keyof U> & U;
type Merge<T, U> = { [K in keyof MergeTwo<T, U>]: MergeTwo<T, U>[K] };

2. 支持多类型合并的递归泛型

如果需要合并任意数量的类型,可以写一个递归工具遍历类型数组:

type MergeAll<T extends any[]> = T extends [infer First, ...infer Rest]
  ? Merge<First, MergeAll<Rest>>
  : {};

3. 使用示例

type A = { foo: string }
type B = { fizz: number }
type C = { bar: boolean }
type D = { buzz: null | string }

// 合并两个类型,直接展开为单个对象
type MergedAB = Merge<A, B>; 
// 类型显示:{ foo: string; fizz: number }

// 合并多个类型
type AllMerged = MergeAll<[A, B, C, D]>;
// 类型显示:{ foo: string; fizz: number; bar: boolean; buzz: null | string }

原理说明

  • MergeTwo先通过Omit<T, keyof U> & U处理键的覆盖逻辑(后传入的类型会覆盖前一个类型的同名键),再通过Merge的映射类型重新构造对象,触发TypeScript的类型展开机制,避免显示为交叉类型。
  • MergeAll利用递归遍历类型数组,逐个合并所有传入的类型,最终得到完全展开的单个对象类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 23:47:16