Vue-router报错Argument of type ... is not assignable to parameter of type 'RouterOptions'的解决方案
这个问题说起来也奇怪,之前一直用得好好的,打包的时候突然router就报错了。报错信息很长,其中最主要的就是这一段:Argument of type '{...(中间一大段代码略过)}' is not assignable to parameter of type 'RouterOptions'.Types of property 'routes' are incompatible....
·
这个问题说起来也奇怪,之前一直用得好好的,打包的时候突然router就报错了。报错信息很长,其中最主要的就是这一段:
Argument of type '{...(中间一大段代码略过)}' is not assignable to parameter of type 'RouterOptions'.
Types of property 'routes' are incompatible.
这种报错一看就是TS的类型异常。修复这个bug也很容易,只需要进行一次类型转换就好了:
const router = new Router({
mode: 'history',
base: process.env.BASE_URL,
routes
} as RouterOptions);
但是为什么呢?
(大段源码预警)
仔细分析一下,发现是升级vue-function-api到2.2.0之后出现了这个问题。2.2.0里对setup的返回值进行了修改,我们可以看看它的类型:
export declare function createComponent<PropsOptions, RawBindings>(options: ComponentOptions<PropsOptions, RawBindings>): VueProxy<PropsOptions, RawBindings>;
import { VueConstructor, VNode, ComponentOptions as Vue2ComponentOptions } from 'vue';
declare type VueProxy<PropsOptions, RawBindings> = Vue2ComponentOptions<never, UnwrapValue<RawBindings>, never, never, PropsOptions, ExtractPropTypes<PropsOptions, false>> & VueConstructorProxy<PropsOptions, RawBindings>;
declare type VueConstructorProxy<PropsOptions, RawBindings> = {
new (): ComponentRenderProxy<ExtractPropTypes<PropsOptions>, UnwrapValue<RawBindings>, ExtractPropTypes<PropsOptions, false>>;
};
declare type ComponentRenderProxy<P = {}, S = {}, PublicProps = P> = {
$data: S;
$props: PublicProps;
$attrs: Data;
$refs: Data;
$slots: Data;
$root: ComponentInstance | null;
$parent: ComponentInstance | null;
$emit: (event: string, ...args: unknown[]) => void;
} & P & S;
从代码里可以看到,这里的返回值类似于一个多继承。也就是说,使用vue-function-api后,返回值变成了Vue2.x和3.x的混合体。而我们再看看router对类型的要求:
export interface RouteConfig {
path: string;
name?: string;
component?: Component;
components?: Dictionary<Component>;
redirect?: RedirectOption;
alias?: string | string[];
children?: RouteConfig[];
meta?: any;
beforeEnter?: NavigationGuard;
props?: boolean | Object | RoutePropsFunction;
caseSensitive?: boolean;
pathToRegexpOptions?: PathToRegexpOptions;
}
type Component = ComponentOptions<Vue> | typeof Vue | AsyncComponent;
export type AsyncComponent<Data=DefaultData<never>, Methods=DefaultMethods<never>, Computed=DefaultComputed, Props=DefaultProps>
= AsyncComponentPromise<Data, Methods, Computed, Props>
| AsyncComponentFactory<Data, Methods, Computed, Props>
export type AsyncComponentPromise<Data=DefaultData<never>, Methods=DefaultMethods<never>, Computed=DefaultComputed, Props=DefaultProps> = (
resolve: (component: Component<Data, Methods, Computed, Props>) => void,
reject: (reason?: any) => void
) => Promise<Component | EsModuleComponent> | void;
export type AsyncComponentFactory<Data=DefaultData<never>, Methods=DefaultMethods<never>, Computed=DefaultComputed, Props=DefaultProps> = () => {
component: AsyncComponentPromise<Data, Methods, Computed, Props>;
loading?: Component | EsModuleComponent;
error?: Component | EsModuleComponent;
delay?: number;
timeout?: number;
}
简而言之,无论是直接导入,还是通过()=>import('foo.vue')
的方式异步加载,这里需要的都是一个Vue2.x里的component。回忆一下在C++里是怎么处理多继承的问题的?强制类型转换来明确类型。所以,vue-function-api带来的交叉类型需要强制类型转换来进行明确;这也就是问题的来源了。
更多推荐
已为社区贡献3条内容
所有评论(0)