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

递归联合类型实现:仅单分支属性可选(支持嵌套对象)

递归处理联合类型的嵌套属性合并与可选化

针对递归需求,我们可以通过遍历类型的每个属性层级,将联合类型中各层级的对象都合并为「共享属性保留,仅部分分支存在的属性设为可选」的结构。以下是完整的类型工具实现:

// 获取联合类型所有分支的全部键名
type AllKeys<T> = T extends unknown ? keyof T : never;

// 判断类型是否为非空对象(排除null、数组等)
type IsObject<T> = T extends object ? T extends null | Array<any> ? false : true : false;

// 递归合并联合类型的每个层级
type MergeUnionRecursive<T> = 
    T extends object 
        ? {
            [K in AllKeys<T>]: 
                // 对每个键,收集所有分支对应的类型并递归处理
                MergeUnionRecursive<
                    T extends { [P in K]?: infer V } ? V : never
                >
        } extends infer Merged
            ? // 过滤掉类型为never的属性,再将仅部分分支存在的属性转为可选
              {
                  [K in keyof Merged as Merged[K] extends never ? never : K]: 
                      Merged[K] extends never ? never : Merged[K]
              } extends infer Final
                  ? Final & Partial<
                        Record<
                            Exclude<AllKeys<T>, keyof Final>, 
                            never
                        >
                    > extends infer Combined
                        ? Omit<Combined, never>
                        : never
            : never
        : T;

// 最终的递归可选化工具类型
type OptionalizeRecursive<T> = MergeUnionRecursive<T>;

测试示例

基础嵌套场景

type X1 = { shared: { x1: number }, x: number };
type Y1 = { shared: { y1: string }, y: number };

type Z1 = OptionalizeRecursive<X1 | Y1>;
/* 最终结果:
type Z1 = {
    shared: {
        x1?: number | undefined;
        y1?: string | undefined;
    };
    x?: number | undefined;
    y?: number | undefined;
} */

多层嵌套场景

type A = { 
    top: { 
        mid: { a: string }, 
        onlyA: boolean 
    } 
};
type B = { 
    top: { 
        mid: { b: number }, 
        onlyB: string 
    } 
};

type MergedAB = OptionalizeRecursive<A | B>;
/* 最终结果:
type MergedAB = {
    top: {
        mid: {
            a?: string | undefined;
            b?: number | undefined;
        };
        onlyA?: boolean | undefined;
        onlyB?: string | undefined;
    };
} */

关键类型说明

  • AllKeys<T>:遍历联合类型的每个分支,收集所有可能的键名,确保不会遗漏任何分支的属性。
  • IsObject<T>:用于判断当前属性值是否为需要递归处理的对象类型,避免对原始类型(如string、number)进行不必要的递归。
  • MergeUnionRecursive<T>:核心递归逻辑,先对每个键的对应类型做递归合并,再过滤无效的never类型属性,最后将仅部分分支存在的键转为可选,得到干净的合并结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 08:24:53