我正在尝试创造一个界面
export interface MenuItem {
title: string;
component?: any;
click?: any;
icon: string;
}
是否有方法要求组件或单击进行设置 是否有一种方法要求两个属性都不能设置?
我正在尝试创造一个界面
export interface MenuItem {
title: string;
component?: any;
click?: any;
icon: string;
}
是否有方法要求组件或单击进行设置 是否有一种方法要求两个属性都不能设置?
当前回答
我喜欢将Pick与包含所有属性的基本类型一起使用,以建立这些类型的条件需求。
interface MenuItemProps {
title: string;
component: any;
click: any;
icon: string;
}
export interface MenuItem =
Pick<MenuItemProps, "title" | "icon" | "component"> |
Pick<MenuItemProps, "title" | "icon" | "click">
这样既干净又灵活。您可以任意地复杂化您的需求,断言诸如“需要所有属性,只需要这两个属性,或者只需要这一个属性”之类的东西,同时保持您的声明简单易读。
其他回答
只是延伸到上面的酷答案!对于登陆这里的人,同时寻找一个需要能力的部分版本!这里有一个片段,我要采取!
PartialReq
你想要一个接口的部分,但同时需要一些字段!这是如何做到的
export type PartialReq<T, Keys extends keyof T = keyof T> =
Pick<Partial<T>, Exclude<keyof T, Keys>>
& {
[K in Keys]: T[K]
};
使用的例子
export interface CacheObj<SigType = any, ValType = any> {
cache: Map<SigType, ValType>,
insertionCallback: InsertionCallback<SigType, ValType> // I want this to be required
}
// ...
export class OneFlexibleCache<SigType = any, ValType = any> {
private _cacheObj: CacheObj<SigType, ValType>;
constructor(
cacheObj: PartialReq<CacheObj<SigType, ValType>, 'insertionCallback'> // <-- here
// i used it
) {
cacheObj = cacheObj || {};
this._cacheObj = {
// ...
// _______________ usage
this._caches.set(
cacheSignature,
new OneFlexibleCache<InsertionSigType, InsertionValType>({
insertionCallback // required need to be provided
})
);
在这里你可以看到它工作得很完美
如未提供要求
更新:对于我在这里暗示的用法,一个更好的答案
我刚从医生那里找到了奥米特。
https://www.typescriptlang.org/docs/handbook/utility-types.html#omittk
我是来加的。但在此之前,我看到了一个很酷的答案。它涵盖了所有:
https://stackoverflow.com/a/48216010/7668448
看看吧!它展示了如何为所有不同版本的Typescript做这件事!为了不重复!去看看!
这种方法结合了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 RequireField<T, K extends keyof T> = T & Required<Pick<T, K>>
用法:
let a : RequireField<TypeA, "fieldA" | "fieldB">;
这使得fieldA和fieldB是必需的。
这里有一个简单的方法来实现其中一个,但不是两个
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"
}
最后我这样做了:
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>;
但希望有一种方法可以用单一界面来建模。