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

jkj*_*ing 63 typescript

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

interface Asset {
  id: string;
  internal_id: string;
  usage: number;
}
Run Code Online (Sandbox Code Playgroud)

这是帖子界面的一部分:

interface Post {
  asset: Asset;
}
Run Code Online (Sandbox Code Playgroud)

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

interface PostDraft {
  asset: Asset;
}
Run Code Online (Sandbox Code Playgroud)

我想允许一个PostDraft对象拥有一个部分资产对象,同时仍然检查那里的属性上的类型(所以我不想只是将其交换掉any).

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

interface AssetDraft {
  id?: string;
  internal_id?: string;
  usage?: number;
}
Run Code Online (Sandbox Code Playgroud)

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

Dav*_*ret 137

如果没有创建具有可选属性的附加接口,则无法在TypeScript <2.1中执行此操作; 但是,这可以通过在TypeScript 2.1+中使用映射类型来实现.

为此,请使用Partial<T>TypeScript默认提供的类型(请参阅此处的定义):

interface PostDraft {
    asset: Partial<Asset>;
}
Run Code Online (Sandbox Code Playgroud)

现在所有属性asset都是可选的,这将允许您这样做:

const postDraft: PostDraft = {
    asset: {
        id: "some-id"
    }
};
Run Code Online (Sandbox Code Playgroud)

在此处手册中阅读有关映射类型的更多信息.

  • 感谢您的工作时间,我刚刚救了我<3! (9认同)
  • 继续对进入 TS 的想法感到惊讶......来自微软的同样如此。希望同样的意图进入他们的网络浏览器开发(-_-) (3认同)
  • @Tony 是的,在 [TS 2.8](https://blogs.msdn.microsoft.com/typescript/2018/03/15/annoucing-typescript-2-8-rc/) 中可以使用条件类型(请参阅`必需&lt;T&gt;`)。 (2认同)
  • 天哪,这是一个如此干净的解决方案。希望我早点知道这一点 (2认同)

Nit*_*mer 8

接口中的属性要么是可选的,要么不是,您不能使用相同的接口一次作为可选和一次必须。

您可以做的是拥有一个具有可选属性的接口,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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这里的默认值是静态成员,但您可以通过其他方式获取它们,或者在缺少它们时抛出错误。

我发现这种方式在使用从服务器(或类似的东西)接收的 json 时非常舒服,接口代表 json 数据,类是使用 json 作为初始值构建的实际模型。


dhi*_*ilt 5

如果我想有一个明确的AssetDraft接口,我会用的组合extendsPartial

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

interface AssetDraft extends Partial<Asset> {}
Run Code Online (Sandbox Code Playgroud)