我的应用程序中有一个界面:
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
接口。有没有办法做到这一点?如果没有,在这种情况下安排我的类型的聪明方法是什么?
答案 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];
};
详细了解映射类型here和in 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
接口,我可以结合使用extends
和Partial
:
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
}
};