Custom plugin in Typescript after Vue 3.4 update
According to Vue 3.4 docs, if I want to define a custom plugin, I need to create it like this:
// my-custom-plugin.ts
export default {
install: (app, options) => {
// do something here with app and options
}
}
Then, on main.ts, I set app to use it:
import App from './App.vue'
import router from './router'
import customPlugin from './my-custom-plugin'
export const app = createApp(App)
app.use(router)
app.use(customPlugin)
And that was OK until I updated Vue to version 3.4.20. I was using 3.2.45 before.
Now, when I try to build the project with yarn build (which uses vite build too) it throws this error:
Argument of type '{ install: (app: App, options: any) => void; }' is not assignable to parameter of type 'Plugin<[]>'.
Type '{ install: (app: App, options: any) => void; }' is not assignable to type 'FunctionPlugin<[]>'.
After searching for type definitiions in node_modules/@vue/runtime-core/dist/runtime-core.d.ts, I found out that, in order to Typescript doesn't claim any type errors, I must define my plugin as an ObjectPlugin type.
I did it this way:
import { ObjectPlugin } from 'node_modules/@vue/runtime-core/dist/runtime-core'
export default {
install: (app, options) => {
// stuff
},
} as ObjectPlugin
I can't use Plugin type because it says that Plugin type is deprecated.
Is my fix correct? How can I contribute so the Vue docs has some notes regarding Typescript support?
@joaoefornazari have you reached the issue on the core repository? It looks like we might improve the code instead of adding a specific section to docs π€
@NataliaTepluhina I'll give a try. This is a thing that never happened to me so I was lost in what to do about it - I thought that there was already something on Vue core that would solve this but people forgot to put it on the docs. That's why I opened the issue.
Maybe I open an issue on vuejs/core? What would you recommend?
I can't use Plugin type because it says that
Plugin type is deprecated.
Where? There is no deprecation notice for that (https://github.com/vuejs/core/blob/01172fdb777f9a0b51781ed2015a1ba3824340a3/packages/runtime-core/src/apiCreateApp.ts#L168). import type { Plugin } from 'vue' should work fine. Also you should not cast it to Plugin, it should be satisfies Plugin:
import type { Plugin } from 'vue'
export default {
install(app, options) {
}
} satisfies Plugin
// or if you're using named exports
export const foo: Plugin = {
install(app, options) {
}
}
I solved the problem that happened with me here.
I did it like this:
my-custom-plugin.ts
// using import { PluginOptions } from 'unocss' also work
import { App, Plugin } from 'vue'
export default {
install: (app: App, options?: any) => {
// stuff using app and options (optional)
},
} satisfies Plugin
main.ts
import App from './App.vue'
import router from './router'
import customPlugin from './my-custom-plugin'
export const app = createApp(App)
app.use(router)
app.use(customPlugin)
Thanks @brc-dd for the clarification! But still, this solution ain't listed on the docs. @NataliaTepluhina Shouldn't it be there?
I have the exact same problem and the above solution did not work for me. I am using Vue version 3.4.26. I am creating a component library. The plugin works fine when I use it directly in my component library, but when I export the plugin and try to use it in another project it throws these errors:
Argument of type '{ install: (app: App<any>) => void; }' is not assignable to parameter of type 'Plugin<[]>'.
Type '{ install: (app: App<any>) => void; }' is not assignable to type 'FunctionPlugin<[]>'.
Type '{ install: (app: App<any>) => void; }' is not assignable to type '(app: App<any>) => any'.
Type '{ install: (app: App<any>) => void; }' provides no match for the signature '(app: App<any>): any'.ts(2345)
I had this issue with v3.4.16, but upgrading to v3.4.29 resolved it.
I'm also seeing this error when bumping to vue version ^3.4.30. Most recent working version is 3.4.25 - Variations of the solutions above do not resolve the problem.
Do any of you have a minimal, reproducible example? Also the code in https://github.com/vuejs/docs/issues/2729#issuecomment-2023953841 is not exactly correct, if you're saying something satisfies Plugin, you don't need type parameters on individual arguments, certainly not two commas and any.
Also it doesn't seem like a docs issue. If you're not able to make something work, a better place to ask might be on https://chat.vuejs.org. In the docs, we can just add a short sub section at https://vuejs.org/guide/reusability/plugins.html#writing-a-plugin showing how to use it with typescript. Basically, something like the equivalent of JS example there:
// plugins/i18n.ts
import type { Plugin } from 'vue'
export default {
install: (app, options) => {
// Plugin code goes here
}
} satisfies Plugin
@brc-dd Oh, sorry. I didn't see the comma lost over there. Also, the comma is not on my original code, so no problem at all - but I'll fix the code on the comment.
And also: adding a short subsection on the Writing a Plugin page would be good IMO. I really like how Vue docs takes care of mentioning Typescript typing when it is the case. The Vue docs is one of the easiest and "straightforward-est" docs to read out there, so it really surprised me to discover that I had to find out the correct Typescript approach by myself. I know this situation can sound simple, but it wasn't obvious to me and apparently it wasn't for some other people too.
EDIT: Code fixed.
Yeah regarding docs I agree. But the last three comments are probably because of something else. They better be posted on discussions/discord. One is saying it works with v3.4.29 and the other is saying that most recent working version is v3.4.25 -- which are obviously conflicting. If any of those can share a repo where this happens we could probably resolve those.
In my particular case, this issue was as a result of a mismatch in package.json files both referencing vue, but with different versions
I meet the same problem with v3.4.29 ,but upgrading to v3.4.30 resolved itγby the way, before I upgrading to v3.4.30, I delete the node_modules and pnpm-lock.yaml, then I reinstall the project by pnpm i , maybe this also help π