将 Typescript 接口中的所有属性设为可选

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39713349/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 07:21:23  来源:igfitidea点击:

Make all properties within a Typescript interface optional

typescript

提问by jkjustjoshing

I have an interface in my application:

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

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

that is part of a post interface:

这是帖子界面的一部分:

interface Post {
  asset: Asset;
}

I also have an interface that is for a post draft, where the asset object might only be partially constructed

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

interface PostDraft {
  asset: Asset;
}

I want to allow a PostDraftobject to have a partial asset object while still checking types on the properties that are there (so I don't want to just swap it out with any).

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

I basically want a way to be able to generate the following:

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

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

without entirely re-defining the Assetinterface. Is there a way to do this? If not, what would the smart way to arrange my types in this situation be?

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

回答by David Sherret

This isn't possible in TypeScript < 2.1 without creating an additional interface with optional properties; however, this is possible by using mapped types in TypeScript 2.1+.

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

To do this, use the Partial<T>type which TypeScript provides by default.

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

interface PostDraft {
    asset: Partial<Asset>;
}

Now all the properties on assetare optional, which will allow you to do the following:

现在所有属性asset都是可选的,这将允许您执行以下操作:

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

About Partial<T>

关于 Partial<T>

Partial<T>is definedas a mapped type that makes every property in the provided type optional (using the ?token).

Partial<T>定义为一种映射类型,它使所提供类型中的每个属性都是可选的(使用?令牌)。

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

Read more about mapped types hereand in the handbook.

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

回答by Nitzan Tomer

The properties in the interface are either optional are not, you can not use the same interface once as optional and once as must.

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

What you can do is to have an interface with optional properties for the AssetDraftand then a class with mandatory properties for the Asset:

您可以做的是拥有一个具有可选属性的接口,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;
    }
}

The default values here are static members, but you can get those in other ways or throw an error in case they are missing.

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

I find this way very comfortable when working with jsons that are received from the server (or something similar), the interfaces represent the json data and the classes are the actual models that are constructed using the jsons as initial values.

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

回答by user3893988

How about force casting an empty object e.g

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

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

If you really really need this then you can always generate a d.ts interface from a template that makes both the optional and typed properties.

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

As Nitzan pointed out, either Typescript interface properties are optional or not

正如 Nitzan 指出的,Typescript 接口属性要么是可选的,要么不是

回答by WebBrother

In addition to David Sherret answerjust a few lines from my side how it can be implemented directly without Partial<T>type for better understanding of the subject.

除了David Sherret 回答我身边的几行之外,如何在没有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
  }
};

回答by dhilt

If I want to have an explicit AssetDraftinterface, I would use a combination of extendsand Partial:

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

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

interface AssetDraft extends Partial<Asset> {}