我正在尝试创造一个界面
export interface MenuItem {
title: string;
component?: any;
click?: any;
icon: string;
}
是否有方法要求组件或单击进行设置 是否有一种方法要求两个属性都不能设置?
我正在尝试创造一个界面
export interface MenuItem {
title: string;
component?: any;
click?: any;
icon: string;
}
是否有方法要求组件或单击进行设置 是否有一种方法要求两个属性都不能设置?
当前回答
这种方法结合了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 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 MenuItem = {
title: string;
component: any;
click?: never;
icon: string;
} | {
title: string;
component?: never;
click: any;
icon: string;
}
// good
const menuItemWithComponent: MenuItem = {
title: 'title',
component: "my component",
icon: "icon"
}
// good
const menuItemWithClick: MenuItem = {
title: 'title',
click: "my click",
icon: "icon"
}
// compile error
const menuItemWithBoth: MenuItem = {
title: 'title',
click: "my click",
component: "my click",
icon: "icon"
}
这种方法结合了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;
//...
}
还有另一个解决方案:
type RequiredKeys<T, K extends keyof T> = Required<Pick<T, K>> & Omit<T, K>;
type MenuItem2 = RequiredKeys<MenuItem, "component" | "click">;