合并DeepPartial / DeepMerge / Confine泛型

时间:2019-02-11 19:55:37

标签: typescript

我正在尝试创建一个相当复杂的泛型。我在StackOverflow上问了很多问题,尝试拼凑我想要的东西,所以我想我只是解释一下我要寻找的东西。

提供一个界面:

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,
    } | string,
  },
};

我正在寻找一种能够从该接口创建另一个接口的方法,该接口在复制某些接口时会限制其范围。

示例

例如,我希望有能力

  • Person.address.address限制为正义字符串
type PersonEdit = {
  address: {
    address: string,
  },
};
  • Person.address.address限制为一个对象
type PersonEdit = {
  address: {
    address: {},
  },
};
  • 将任何属性更改为可选,
type PersonEdit = {
  address: {
    address?: {} | string,
  },
};
  • Person.address.address.zip限制为一个数字
type PersonEdit = {
  address: {
    address: {
      zip: number
    },
  },
};

要求

  • 我希望能够只关注嵌套属性,并从接口的其余部分继承所有其他类型。
  • 这些Edits应该是来源的DeepPartial<>,并且不允许父级不在的新属性或联合。

现有的泛型

这是StackOverflow上的优秀人们帮助我提出的,与我所问的其他问题相距甚远。

type Confine<A, B extends { [K in keyof B]: K extends keyof A ? A[K] : never }> = B;
type DeepPartial<T> = {
  [P in keyof T]?: T[P] extends (infer U)[]
  ? DeepPartial<U>[]
  : T[P] extends ReadonlyArray<infer U>
      ? ReadonlyArray<DeepPartial<U>>
      : DeepPartial<T[P]>
};

type DeepMerge<T, U> = T extends any ? U extends any ?
  [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 : never : never;

更新

type DeepMerge<T, U> = T extends any ? U extends DeepPartial<T> ?
  [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 : never : never;

这很好用,但不能限制U来不添加任何新属性。

0 个答案:

没有答案