TypeScript 2.1中的递归部分<t>

时间:2017-02-01 12:44:53

标签: typescript typescript2.1

我有这个界面:

export interface UserSettings
{
    one: {
        three: number;
        four: number;
    };
    two: {
        five: number;
        six: number;
    };
}

...并想把它变成这个:

export interface UserSettingsForUpdate
{
    one?: {
        three?: number;
        four?: number;
    };
    two?: {
        five?: number;
        six?: number;
    };
}

...但是Partial<UserSettings>产生了这个:

{
    one?: {
        three: number;
        four: number;
    };
    two?: {
        five: number;
        six: number;
    };
}

是否可以使用映射类型使所有深度上的所有属性都可选,或者我是否必须手动创建接口?

4 个答案:

答案 0 :(得分:18)

随着2.8中的条件类型的登陆,我们现在可以如下声明一个递归部分类型。

type RecursivePartial<T> = {
  [P in keyof T]?:
    T[P] extends (infer U)[] ? RecursivePartial<U>[] :
    T[P] extends object ? RecursivePartial<T[P]> :
    T[P];
};

参考:

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

答案 1 :(得分:15)

您可以创建自己的映射类型,如下所示:

type RecursivePartial<T> = {
    [P in keyof T]?: RecursivePartial<T[P]>;
};

enter image description here

不幸的是,这对于数组类型的字段不起作用。 似乎还没有办法进行条件类型映射;即限制原语。请参阅https://github.com/Microsoft/TypeScript/pull/12114#issuecomment-259776847现在可能,请参阅其他答案。

答案 2 :(得分:1)

所提供的解决方案都不够好。这是一个解释:

const x: RecursivePartial<{dateValue: Date}> = {dateValue: 0}; // ja-ja-ja

在上面的代码中,dateValue的实际类型是RecursivePartial<Date> | undefined,它可以分配任何值!!! dateValue的预期类型仅为Date,但是规则T[P] extends object ? RecursivePartial<T[P]>太宽。

解决方案是分离基元并消除extends object

export type RecursivePartial<T> = {
    [P in keyof T]?:
    T[P] extends Array<infer U> ? Array<Value<U>> : Value<T[P]>;
};
type AllowedPrimitives = boolean | string | number | Date /* add any types than should be considered as a value, say, DateTimeOffset */;
type Value<T> = T extends AllowedPrimitives ? T : RecursivePartial<T>;

答案 3 :(得分:0)

我已经建立了一个图书馆tsdef,该图书馆具有许多类似的常见模式/摘要。

在这种情况下,您可以像下面这样使用它:

import { DeepPartial } from 'tsdef';

let o: DeepPartial<{a: number}> = {};