Open backbone87 opened 6 years ago
This is because Component
type is a union type with VueConstructor
and ComponentOptions
.
Why do you use Component
type? It means your getComponent
function can return both Vue constructor and component options object.
I think you should use more concrete type such as VueConstructor
or ComponentOptions
as the return type.
Because the function loads components via webpacks require.context. Also there is a EsModule type for async comps that hints against Component. There is also a Vue.component overload foreach member type of the Component union. I think that is just a problem of typescript not being able to check that correctly.
Another indicator for this being a ts problem is that the following works:
const comp: Component = {};
Vue.component('test', comp);
well, {}
is a valid component
ofc it is. that is not the point. but then TS somehow finds the correct Vue.component
overload:
// type Component = typeof Vue | ComponentOptions | FunctionalComponentOptions;
const first = {};
const firstComponent: Component = first;
Vue.component('first', first); // ok
Vue.component('firstComponent', firstComponent); // ok
const second = { functional: true };
const secondComponent: Component = second;
Vue.component('second', second); // ok
Vue.component('secondComponent', secondComponent); // ok
const third = Vue.extend({});
const thirdComponent: Component = third;
Vue.component('thrid', third); // ok
Vue.component('thirdComponent', thirdComponent); // ok
declare function getComponent(): Component;
const final: Component = getComponent();
Vue.component('final', final); // type error
It is a typescript problem. TS seems like it doesnt allow multiple overloads to match (what the final case is requiring).
here is a plain typescript example demonstrating the problem:
interface A {
a: string;
}
interface B {
b: string;
}
interface C {
c: string;
}
type union = A | B | C;
declare function acceptsUnion(x: A): void;
declare function acceptsUnion(x: B): void;
declare function acceptsUnion(x: C): void;
declare function returnsUnion(): union;
acceptsUnion(returnsUnion()); // type error
I see your use case. I'm not sure that union type sometimes passes overload but we can replace fallback overload of component
method with Component
type.
any update on this?
i am using the following vue.d.ts
in my projects, which solves the type problem according to @ktsn proposed solution:
import Vue, { Component } from 'vue';
import { ExtendedVue } from 'vue/types/vue';
declare module 'vue/types/vue' {
interface VueConstructor<V extends Vue = Vue> {
component<Data, Methods, Computed, Props>(
id: string,
definition: Component<Data, Methods, Computed, Props>,
): ExtendedVue<V, Data, Methods, Computed, Props>;
}
}
Version
2.5.17
Reproduction link
https://codesandbox.io/s/8z04jxj3y8
Steps to reproduce
What is expected?
I can pass any component to
Vue.component
What is actually happening?
Type error:
Adding the following overload to
Vue.component
will fix it: