使Typescript接口中的所有属性都可选

时间:2016-09-26 22:25:21

标签: typescript

我的应用程序中有一个界面:

interface Asset {
  id: string;
  internal_id: string;
  usage: number;
}

这是帖子界面的一部分:

interface Post {
  asset: Asset;
}

我还有一个用于帖子草稿的界面,其中资产对象可能只是部分构建

interface PostDraft {
  asset: Asset;
}

我想允许PostDraft对象拥有部分资产对象,同时仍然检查其中属性的类型(因此我不想将其与any交换出来)。

我基本上想要一种能够生成以下内容的方法:

interface AssetDraft {
  id?: string;
  internal_id?: string;
  usage?: number;
}

没有完全重新定义Asset接口。有没有办法做到这一点?如果没有,在这种情况下安排我的类型的聪明方法是什么?

5 个答案:

答案 0 :(得分:91)

这在TypeScript<中是不可能的。 2.1不创建具有可选属性的附加接口;但是,这可以通过在TypeScript 2.1 +中使用映射类型来实现。

为此,请使用TypeScript默认提供的Partial<T>类型。

interface PostDraft {
    asset: Partial<Asset>;
}

现在asset上的所有属性都是可选的,这样您就可以执行以下操作:

const postDraft: PostDraft = {
    asset: {
        id: "some-id"
    }
};

关于Partial<T>

Partial<T>defined作为映射类型,它使每个属性都可选(使用?令牌)。

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

详细了解映射类型herein the handbook

答案 1 :(得分:3)

界面中的属性要么是可选的,要么不能使用同一个界面作为可选项,必须使用一次。

你可以做的是拥有一个带有AssetDraft可选属性的接口,然后是一个具有Asset强制属性的类:

interface AssetDraft {
    id?: string;
    internal_id?: string;
    usage?: number;
}

class Asset {
    static DEFAULT_ID = "id";
    static DEFAULT_INTERNAL_ID = "internalid";
    static DEFAULT_USAGE = 0;

    id: string;
    internal_id: string;
    usage: number;

    constructor(draft: AssetDraft) {
        this.id = draft.id || Asset.DEFAULT_ID;
        this.internal_id = draft.internal_id || Asset.DEFAULT_INTERNAL_ID;
        this.usage = draft.usage || Asset.DEFAULT_USAGE;
    }
}

这里的默认值是静态成员,但是你可以通过其他方式获取它们,或者在它们丢失的情况下抛出错误。

在使用从服务器(或类似的东西)接收的jsons时,我觉得这很方便,接口代表json数据,类是使用jsons作为初始值构造的实际模型。 p>

答案 2 :(得分:1)

如果我想有一个明确的AssetDraft接口,我可以结合使用extendsPartial

interface Asset {
  id: string;
  internal_id: string;
  usage: number;
}

interface AssetDraft extends Partial<Asset> {}

答案 3 :(得分:0)

如何强制投射空物体,例如

const draft = <PostDraft>{}
draft.id = 123
draft.internal_id = 456
draft.usage = 789

如果你确实真的需要这个,那么你总是可以从一个模板中生成一个d.ts接口,该模板同时生成可选属性和类型属性。

正如Nitzan指出的那样,Typescript接口属性是可选的还是

答案 4 :(得分:0)

除了David Sherret answer之外,我还有几行内容是如何直接实现而无需使用Partial<T>类型,以便更好地理解该主题。

interface IAsset {
  id: string;
  internal_id: string;
  usage: number;
}

interface IPost {
  asset: IAsset;
}

interface IPostDraft {
  asset: { [K in keyof IAsset]?: IAsset[K] };
}

const postDraft: IPostDraft = {
  asset: {
    usage: 123
  }
};