Typescript - Слияние глубокого типа, включая дополнительные свойства - PullRequest
1 голос
/ 23 февраля 2020

До сих пор я использовал оператор пересечения (&) для объединения двух типов объектов. В некоторых случаях пересечение не подходит:

  • Свойство объекта типа существует в обоих объектах, и я хотел бы объединить их
  • Необязательное свойство существует в оба объекта.
  • Необязательное свойство типа object существует в обоих объектах.

Я ищу обобщенный c, который также может обрабатывать эти случаи.

Этот ответ показывает, как можно выделить необязательные свойства.

1 Ответ

1 голос
/ 23 февраля 2020

Во-первых, спасибо за ссылку для аналогичной проблемы, я взял оттуда тип утилиты - 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
}

Мы сделали три шага:

  • type First представляет все поля T1 +, если T2 имеет то же самое поле, которое мы объединяем с помощью объединения
  • тип OptionalSecond представляет поля, которые являются необязательными в T2, но не использовались в типе First. Мы говорим здесь +?, чтобы эти поля оставались необязательными, здесь
  • type NonOptionalSecond представляет каждое поле в T2, которое является дополнительным и необязательным

В результате мы имеем все необязательные поля обоих типов, также в случае дублирования объединение выполняется объединением.

...