我正在尝试创造一个界面
export interface MenuItem {
title: string;
component?: any;
click?: any;
icon: string;
}
是否有方法要求组件或单击进行设置 是否有一种方法要求两个属性都不能设置?
我正在尝试创造一个界面
export interface MenuItem {
title: string;
component?: any;
click?: any;
icon: string;
}
是否有方法要求组件或单击进行设置 是否有一种方法要求两个属性都不能设置?
当前回答
最后我这样做了:
export interface MenuItem {
title: string;
icon: string;
}
export interface MenuItemComponent extends MenuItem{
component: any;
}
export interface MenuItemClick extends MenuItem{
click: any;
}
然后我用了:
appMenuItems: Array<MenuItemComponent|MenuItemClick>;
但希望有一种方法可以用单一界面来建模。
其他回答
不是用一个接口,因为类型没有条件逻辑,不能相互依赖,但你可以通过分离接口:
export interface BaseMenuItem {
title: string;
icon: string;
}
export interface ComponentMenuItem extends BaseMenuItem {
component: any;
}
export interface ClickMenuItem extends BaseMenuItem {
click: any;
}
export type MenuItem = ComponentMenuItem | ClickMenuItem;
我用这个:
type RequireField<T, K extends keyof T> = T & Required<Pick<T, K>>
用法:
let a : RequireField<TypeA, "fieldA" | "fieldB">;
这使得fieldA和fieldB是必需的。
这种方法结合了never和省略。这样做的好处是易于理解,如果需要添加更多属性,也易于更新。
interface Base {
title: string;
icon: string;
component?: never;
click?: never;
}
interface OnlyComponent {
component: any;
}
interface OnlyClick {
click: any;
}
export type MenuItem = (Omit<Base, 'component'> & OnlyComponent) | (Omit<Base, 'click'> & OnlyClick);
你可以使用in来缩小MenuItem的一个实例:
const item: MenuItem = {
title: 'A good title';
icon: 'fa-plus';
component: SomeComponent;
};
//...
if('component' in item) {
const Comp = item.component;
//...
}
最后我这样做了:
export interface MenuItem {
title: string;
icon: string;
}
export interface MenuItemComponent extends MenuItem{
component: any;
}
export interface MenuItemClick extends MenuItem{
click: any;
}
然后我用了:
appMenuItems: Array<MenuItemComponent|MenuItemClick>;
但希望有一种方法可以用单一界面来建模。
没有多个接口的替代方案是
export type MenuItem = {
title: string;
component: any;
icon: string;
} | {
title: string;
click: any;
icon: string;
};
const item: MenuItem[] = [
{ title: "", icon: "", component: {} },
{ title: "", icon: "", click: "" },
// Shouldn't this error out because it's passing a property that is not defined
{ title: "", icon: "", click: "", component: {} },
// Does error out :)
{ title: "", icon: "" }
];
我在如何创建一个需要设置单个属性的Partial-like中问过类似的问题
上面的内容可以简化,但它可能更容易阅读,也可能不容易
export type MenuItem = {
title: string;
icon: string;
} & (
{component: any} | {click: string}
)
注意,这些都不会阻止你同时添加两者,因为TypeScript确实允许在使用AND/OR的对象上添加额外的属性,请参阅https://github.com/Microsoft/TypeScript/issues/15447