假设我有菜单界面:
interface IMenuBase {
id: number;
title: string;
items: IMenuBase[]; <- children
}
现在我想扩展它。为此,我定义了另一个接口:
interface ICustomMenu extend IMenuBase {
concrete: string;
}
问题在于,items
仍然是IMenuBase。
我试图通过这种方式解决它:
interface IMenuBase<T extends IMenuBase<T>> {
id: number;
title: string;
items: T[];
}
interface ICustomMenu extends IMenuBase<ICustomMenu> {
concrete: string;
}
但是现在我希望能够不带类型地使用IMenuBase。 这是我的playground。
答案 0 :(得分:1)
您有两种可能。您可以采用当前使基类通用的解决方案,并为type参数添加默认值:
interface IMenuBase<T extends IMenuBase<T> = IMenuBase<T>> {
id: number;
title: string;
items: T[];
}
interface ICustomMenu extends IMenuBase<ICustomMenu> {
concrete: string;
}
const testBase = {} as IMenuBase;
testBase.items[0].items[0].id;
const testConcrete = {} as ICustomMenu;
testConcrete.items[0].items[0].concrete;
上面的代码有一个问题,它仅适用于3个级别(我认为默认值的递归性受编译器的限制)
一个更好的选择可能是使用多态this
来指定子代与当前类型属于同一类型,无论该类型是什么:
interface IMenuBase {
id: number;
title: string;
items: this[];
}
interface ICustomMenu extends IMenuBase {
concrete: string;
}
const testBase = {} as IMenuBase;
testBase.items[0].items[0].id;
const testConcrete = {} as ICustomMenu;
testConcrete.items[0].items[0].concrete;