将 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
Make all properties within a Typescript interface optional
提问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 PostDraft
object 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 Asset
interface. 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 asset
are 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 AssetDraft
and 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 AssetDraft
interface, I would use a combination of extends
and Partial
:
如果我想有一个明确的AssetDraft
接口,我会用的组合extends
和Partial
:
interface Asset {
id: string;
internal_id: string;
usage: number;
}
interface AssetDraft extends Partial<Asset> {}