在typescript中使用嵌套属性中的Partial

dag*_*da1 23 typescript

说我有这样的类型;

interface State {
  one: string,
  two: {
    three: {
      four: string
    },
    five: string
  }
}
Run Code Online (Sandbox Code Playgroud)

我像这样制作州部分 Partial<State>

但是我如何才能使嵌套属性成为局部,例如,如果我想使其two也部分.

我该怎么做?

CRi*_*ice 45

您可以非常轻松地定义自己的RecursivePartial类型,这将使​​所有属性(包括嵌套的属性)可选:

type RecursivePartial<T> = {
    [P in keyof T]?: RecursivePartial<T[P]>;
};
Run Code Online (Sandbox Code Playgroud)

如果您只想要将某些属性设置为部分属性,则可以将其与交叉点一起使用Pick:

type PartialExcept<T, K extends keyof T> = RecursivePartial<T> & Pick<T, K>;
Run Code Online (Sandbox Code Playgroud)

这将使一切都是可选的,除了K参数中指定的键.

  • 对于Required而不是Partial则相反: `export type RecursiveRequired&lt;T&gt; = { [P in keyof T]-?: RecursiveRequired&lt;T[P]&gt;; }; ` (2认同)
  • 当一个或属性是任何类型的数组时,@CRice 会遇到一些编译错误。您能想到这样做的任何原因或建议吗?Stackblitz 在这里:https://stackblitz.com/edit/typescript-zscugv (2认同)
  • @MCFreddie777 总有一种方法,你只需要以某种方式捕获该案例。例如,使用`type DeepPartial&lt;T&gt; = T extends never[] ?T : {[P in keyof T]?: DeepPartial&lt;T[P]&gt;}` 将正确捕获 `any[]` 类型的项目,如果需要其他类型,您可以继续调整它。 (2认同)

Sha*_*ard 13

这是可能的,您可以创建一个"深度"部分类型,如下所示:

type DeepPartial<T> = {
    [P in keyof T]?: DeepPartial<T[P]>;
};
Run Code Online (Sandbox Code Playgroud)

可以按照以下方式使用

const state: DeepPartial<State> = {
    two: {
        three: {
            four: '4'
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Sou*_*ter 8

对象上的数组属性

对于 TypeScript 2.8 或更高版本,以下类型应该修复有关 Array 属性的问题:

type NestedPartial<T> = {
    [K in keyof T]?: T[K] extends Array<infer R> ? Array<NestedPartial<R>> : NestedPartial<T[K]>
};
Run Code Online (Sandbox Code Playgroud)

请看下面的例子。

interface Foo {
    NumProp: number;
    SubItem: Foo;
    SubItemArray: Foo[];
}
Run Code Online (Sandbox Code Playgroud)

条件类型的有效结果

有效结果

结果无效

结果无效

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html