TS 的 vue 项目中,有如下代码块简化如下:
<n-menu
:render-extra="renderMenuExtra"
/>
其中,render-extra
报错为:
项目地址:https://github.com/lingkai5wu/link-admin
问题代码位于这里
类型位于这里
MenuOptionWithEx
是我扩展 MenuOption
的类型,相关信息如下:
type MenuOptionWithEx = MenuVO &
MenuOption & {
meta?: RouteMeta
}
export interface MenuVO {
id: number
pid: number
type: MenuTypeEnum
label: string | null
path: string | null
}
// MenuOption 为 Naive UI 内置类型
export type MenuOption = (MenuOptionSharedPart & {
/** @deprecated */
title?: string | (() => VNodeChild);
}) | (MenuOptionSharedPart & {
label?: string | (() => VNodeChild);
});
// 同上
export interface MenuOptionSharedPart {
key?: Key;
disabled?: boolean;
icon?: () => VNodeChild;
children?: Array<MenuOption | MenuGroupOption | MenuDividerOption>;
extra?: string | (() => VNodeChild);
props?: HTMLAttributes;
show?: boolean;
[key: string]: unknown;
/** @deprecated */
titleExtra?: string | (() => VNodeChild);
}
// RouteMeta 为 Vue Router 内置类型
export declare interface RouteMeta extends Record<string | number | symbol, unknown> {
}
我尝试使用联合类型扩展 MenuOptionWithEx
,使 MenuOptionWithEx
为子类型,MenuOption
为父类型,期望满足 TS 的要求,但仍然报错,如上。
经过测试,我发现将 MenuOptionWithEx
中的 MenuVO
从联合类型中移除,就不会出现报错,但这不符合业务逻辑...
我也尝试直接继承 MenuOption
,但 MenuOption
是联合类型,似乎没法直接继承。
这涉及到一个 协变逆变 概念
对于函数参数是反过来,是父类型赋要值给子类型,符合类型安全,可以做个简单的例子:
当然你可以把这个开关关掉
strictFunctionTypes
,不过不建议这样子做