首页 > 解决方案 > Typescript - 深度类型合并,包括可选属性

问题描述

到目前为止,我一直在使用交集 ( &) 运算符来合并两种对象类型。在某些情况下,交叉点不会:

我正在寻找一种也可以处理这些情况的通用产品。

这个答案显示了如何隔离可选属性。

标签: typescripttypescript-typings

解决方案


首先感谢您提供类似问题的链接,我从那里获取了实用程序类型 - OptionalPropertyOf。下面是你的问题的解决方案

type OptionalPropertyOf<T> = Exclude<{
  [K in keyof T]: T extends Record<K, T[K]>
    ? never
    : K
}[keyof T], undefined>

type Merge<T1, T2,
    First = {
        [K in (keyof T1)]: K extends keyof T2 ? T1[K] | T2[K] : T1[K]
    }, OptionalSecond = {
        [K in Exclude<OptionalPropertyOf<T2>, keyof T1>]+?: T2[K]
    },
    NonOptionalSecond = {
        [K in Exclude<keyof T2, keyof First | keyof OptionalSecond>]: T2[K]
    }> = First & OptionalSecond & NonOptionalSecond

// Example
type A = {
    a: string,
    b?: number,
    f: number,
}
type B = {
    a: boolean,
    b? : string,
    c?: string,
    e: number
}
type C = Merge<A, B>
/* type C evaluated as
{
    a: string | boolean;
    b?: string | number | undefined;
    f: number;
    c?: string | undefined;
    e: number;
}

*/
const value: C = {
    a: true,
    e: 1,
    f: 2
}

我们做了三个步骤:

  • typeFirst表示T1+ 的所有字段 ifT2有相同的字段我们通过 union 合并
  • typeOptionalSecond表示可选T2但未在 type 中使用的字段First。我们在这里说+?是为了说明这些字段在这里仍然是可选的
  • typeNonOptionalSecond表示其中的每个字段T2是附加的和非可选的

结果我们拥有两种类型的所有可选字段,在重复合并的情况下也是由联合完成的。


推荐阅读