I’m working with typescript and vue.
In my app there is a service
which is a global for every sub component.
I found this native vue solution on vue JS to inject this property on the child components.
on main.ts
const service = new MyService(...); new Vue({ router, provide() { return { service }; } // provide the service to be injected render: h => h(App), }).$mount("#app");
on any typescript vue component
import Vue from "vue"; export default Vue.extend({ inject: ["service"], // inject the service mounted() { console.log(this.service); // this.service does exists }, });
This way I’m able to get the injected service
on my Child components.
However I’m getting the fallowing error
Property ‘service’ does not exist on type ‘CombinedVueInstance < Vue, {}, {}, {}, Readonly < Record < never, any > > >’.
How can I solve this typescript compilation error?
Advertisement
Answer
Using Vue property decorator
Vue-property-decorator, which internally re-exports decorators from vue-class-component, expose a series of typescript decorators that give really good intellisense. You must use the class api though.
@Inject
and @Provide
are two of such decorators:
In the provider:
import {Vue, Component, Provide} from 'vue-property-decorator'; @Component export default class MyClass { @Provide('service') service: Service = new MyServiceImpl(); // or whatever this is }
In the provided component:
import {Vue, Component, Inject} from 'vue-property-decorator'; @Component export default class MyClass { @inject('service') service!: Service; // or whatever type this service has mounted() { console.log(this.service); // no typescript error here }, }
This I think is the optimal solution, in the sense it gives the better intellisense available when working with Vue.
Now, however, you may don’t want to change the definition of all your components or simply cannot due to external constraints. In such case you can do the next trick:
Casting this
You can cast this
to any whenever you’re about to use this.service
. Not probably the best thing, but it works:
mounted() { console.log((this as any).service); },
There must be other ways, but I’m not used to Vue.extends
api anymore. If you have the time and the opportunity, I strongly suggest you to switch to the class API and start using the vue-property-decorators, they really give the best intellisense.