通用与覆盖属性来创建界面

问题描述 投票:1回答:2

给定一个Person类型

type Person = {
  name: string,
  age: number,
  address: {
    line1: string,
    line2: string | null | number,
    zip: string | number,
  },
};

我想申请重写和修改此接口。

type PersonOverwrites = {
  address: {
    line2?: string,
    zip: string,
  },
};

从这两个接口,我想创建此:

type PersonModified = {
  name: string,
  age: number,
  address: {
    line1: string,
    line2?: string,
    zip: string,
  },
}

这就是我要找:

type PersonModified = Overwrite<Person, PersonOverwrites>

如何建立这种类型的通用的?

更新

这应该抱怨:

type DeepMerge<T, U> = [T, U] extends [object, object] ?
  {
    [K in keyof (U & Pick<T, Exclude<keyof T, keyof U>>)]: (
      K extends keyof U ? (
        K extends keyof T ? DeepMerge<T[K], U[K]> : U[K]
      ) : (
        K extends keyof T ? T[K] : never
      )
    )
  } : U;


type Person = {
  name: string,
  age: number,
  address: {
    line1: string,
    line2: string | null | number,
    zip: string | number,
    address?: {
        line1: string,
        line2: string | null | number,
        zip: string | number,
        address?: {
            line1: string,
            line2: string | null | number,
            zip: string | number,
        },
    },
  },
};

type PersonOverwrites = {
    address: {
        line2?: string,
        zip: string,
        address?: {
            address: {
                pizzaDelivery: boolean,
            },
        },
    },
};

const person: Person = {
    name: 'Thomas',
    age: 12,
    address: {
        line1: 'hi',
        line2: 'hi',
        zip: 'hi',
        address: {
            line1: 'hi',
            line2: 'hi',
            zip: 'hi',
            address: {
                line1: 'hi',
                line2: 'hi',
                zip: 'hi',
                // pizzaDelivery: true,
            }
        }
    }
}
typescript
2个回答
3
投票

我不知道你想这是多么深刻嵌套的,但你可能想是这样的:

type DeepMerge<T, U> = [T, U] extends [object, object] ?
  {
    [K in keyof (U & Pick<T, Exclude<keyof T, keyof U>>)]: (
      K extends keyof U ? (
        K extends keyof T ? DeepMerge<T[K], U[K]> : U[K]
      ) : (
        K extends keyof T ? T[K] : never
      )
    )
  } : U;

type PersonModified = DeepMerge<Person, PersonOverwrites>

这个想法是,DeepMerge<T, U>计算结果为刚刚U如果任TU不是对象类型,或者它走过TU每个组合键,更深入地融合。围绕如何确定哪些属性应该是可选的,以及它如何决定何时停止合并的细节是简单,但繁琐的解释。如果你需要的东西具体阐述,让我知道。

您可以验证PersonModified相当于

type PersonModified = {
    address: {
        line2?: string | undefined;
        zip: string;
        line1: string;
    };
    name: string;
    age: number;
}

为你想。

希望帮助;祝好运!


0
投票

@jcalz答案的建设,我相信这能解决问题可选。

type Merge<M, N> = Omit<M, Extract<keyof M, keyof N>> & N;

type DeepMerge<T, U> = [T, U] extends [object, object] ?
  {
    [K in keyof (Merge<T, U>)]: (
      K extends keyof U ? (
        K extends keyof T ? DeepMerge<T[K], U[K]> : U[K]
      ) : (
        K extends keyof T ? T[K] : never
      )
    )
  } : Merge<T, U>;
© www.soinside.com 2019 - 2024. All rights reserved.