Type Error when implementing Vue "Plugin" type in TypeScript
Vue version
3.3.4
Link to minimal reproduction
https://stackblitz.com/edit/vitejs-vite-gbgbxq?terminal=build
Steps to reproduce
Stackbliz link shows the TS compile error in plugin.ts.
Run npm run build
This example shows a type error in vue plugin implementation.
src/plugins/plugin.ts:9:41 - error TS2422: A class can only implement an object type or intersection of object types with statically known members.
What is expected?
Vue types provide Plugin, PluginInstallFunction and others for plugin implementation. It should be properly used for implementation of plugins without Type Error as above. I would like to ask you to consider revising Type definitions for Plugin.
What is actually happening?
This vue plugin is a class implementation which has 'install' function, which comply with a general guidance of vue plugin implementation.
In a sense of strict type manner for vue plugin implementation, this example tried to "implements" vue Plugin type to the class. But, the Plugin type is not working with class's "implements" directive of TypeScript, since the type is likely dynamic and undetermined for the target class or so on. Thus, we see the following error when compiling *.ts
.
src/plugins/plugin.ts:9:41 - error TS2422: A class can only implement an object type or intersection of object types with statically known members.
System Info
System:
OS: Linux 5.15 Ubuntu 22.04.2 LTS 22.04.2 LTS (Jammy Jellyfish)
CPU: (2) x64 Intel(R) Core(TM)2 Duo CPU P9700 @ 2.80GHz
Memory: 1.79 GB / 7.70 GB
Container: Yes
Shell: 5.1.16 - /bin/bash
Binaries:
Node: 19.6.0 - ~/.nvm/versions/node/v19.6.0/bin/node
Yarn: 1.22.19 - /usr/bin/yarn
npm: 9.4.0 - ~/.nvm/versions/node/v19.6.0/bin/npm
Any additional comments?
Thanks in advance for your taking a look for this issue!
In Vue, the Plugin interface is a union type. A class cannot implement a union type, so you can define its custom type.
interface IPlugin<T = any> {
install: (app: App, options: T) => any
}
class MyPlugin implements IPlugin<Record<name,string>> {
install(app: App, options: Record<name,string> ) {}
}
Alternatively, you can omit the "implements" keyword. You just need to ensure that the class implements the "install" method according to the definition of the Plugin interface.
@Alfred-Skyblue, thanks for your comments. Yes, that's what I am doing for my plugin module.
There is a type definition of "Plugin" in Vue types. But. it's not usable. Then, why is it there? So, that's why I came here to raise this issue. I am seeking a solution with leveraging the Vue types in the box, rather than such custom solutions.
Because Plugin
is a union type, its original intention is to constrain objects, rather than to implement a class, or you can directly implement a plugin using the object-oriented approach.
const myPlugin: Plugin = {
install(app: App) {}
}