我是怎么解决:写Vue3组件库时遇到的一个和 github 还没有 Close 的 issue 一样的问题:Argument of type ‘{ install: (app: App<any>..

开源 0

今天在自己组件库打包成功后,发现在新项目中 用app.use的方式全局挂载自己的组件库有 TS 类型错误,而且发现最近 github 上有不少人也遇到过这个问题,但是还没有解决。

我自己根据社区的思路和方法,尝试了一些方法,在我自己的项目中问题解决了,前后大概花了两三个小时,所以自己记录和分享一下自己解决的思路,希望对大家有帮助。有不对的地方还请多多指教。

报错如下

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)

我自己的项目环境

我用的是 Vue 3.4.29,vite 5, Typescript 5.4。用的 vite-plugin-dts 来进行.d.ts类型文件导出,我最终的组件库的index.ts文件也就是打包入口,源码如下:

// 导入类型定义,增强类型检查import type { App } from "vue";// 导入单个组件import Button from "@/components/Button";// 导入Collapse组件及CollapseItemimport Collapse, { CollapseItem } from "@/components/Collapse";// 导入FontAwesome的SVG核心库和免费的solid图标集import { library } from "@fortawesome/fontawesome-svg-core";import { fas } from "@fortawesome/free-solid-svg-icons";// 引入全局样式文件import "./styles/index.css";// 将FontAwesome的solid图标集添加到库中library.add(fas);// 定义一个组件数组,包含所有需要安装的组件const components = [Button, Collapse, CollapseItem];// 定义一个插件对象,包含install方法用于将组件安装到Vue应用中const installComponents = {  // 安装方法,接收一个Vue应用实例作为参数  install(app: App) {    // 遍历组件数组,将每个组件注册为Vue应用的全局组件    components.forEach(component => {      app.component(component.name as string, component);    });  }};// 导出单个组件,供外部单独使用export { Button, Collapse, CollapseItem };// 导出组件安装插件,供Vue应用使用export default installComponents;

大致就是说导出的插件类型不匹配。

分析报错

报错是一个 TS 类型报错,说我的installComponents对象不能被用作插件,因为没有实现Plugin<[]>接口。

尝试解决

排除自身代码问题

首先我是看了自己的插件能不能在组件库中正确使用,于是我在 main.ts 中使用 app.use 安装全局组件,发现是可以使用的。

然后我就去看了组件库代码的类型文件有没有正确生成,发现在dist文件夹中已经生成了index.d.ts文件,里面有插件的类型声明。

查看官方文档

接着就去找了 Vue 官方文档,专门又仔细得看了一下关于 Plugin 插件的部分,文档中只讲了如何定义和使用,没有提及Plugin<[]>这个插件接口,所以就自己尝试去社区解决了。

借鉴类似的成品

我还去大型的 Vue3 的开源组件库比如 element-plus 和 antd-vue 的关于 install 部分的源码,看了个大概只能说除了一堆 TS 和封装处理,并没有发现什么特别的导出方式,也许是自己水平有限 hhh,自己模仿着改了一下自己的代码,发现并没有什么卵用。

去社区和问 AI

去了国内外博客和问答社区发现几乎没有解决这个问题的相关文章,去问 AI,AI 给出的解决方案写出来一堆错误和警告,而且完全没用,你跟他反馈,它跟你搁那上上下下左右左右 BABA,反复横跳扯皮。

去 issue 仓库

最后就去了 vue 的 github issue 仓库,最终找到了一个和我几乎一样的问题的issue

这个 issue 还挺新的,而且还没有 Close,我看了一下 Vue 官方的维护的人说根据 issue 描述没法复现错误 hhh,所以还没解决。我后续自己尝试解决了后也给出了我的解决办法,希望能够为开源和社区做出一点贡献 hhh

issue 里面评论区时不时地有人碰到一样的问题,有些已经在自己的项目中解决了,但是也是糊里糊涂地解决了,我尝试了这些方法,虽然自己的问题解决了,但是也是稀里糊涂地 hhh。下面我就介绍一下 issue 中给出的解决方法。

解决方案

这里解决方案只是 issue 里面讨论的,正确与否是未知的,但是经过我测试,有些是可以解决我的问题的。大家如果遇到了就自己挨个在自己项目中尝试,毕竟人家官方维护团队都还没解决。。。

方案一

指定导出的插件为 Plugin 类型,例如:

import type { Plugin } from "vue";// 指定导出的插件为 Plugin 类型export default {  install(app, options) {}} satisfies Plugin;// 或者使用默认导出名称export const foo: Plugin = {  install(app, options) {}};

这种方案 对我的组件库项目没有生效,但是对有些人是有效的,可自行尝试。

方案二

尝试将组件库的 Vue 版本和自己项目中使用的 Vue 版本保持一致。这个对我的组件库项目也没有生效,但是对某些人有效,可自行尝试。

方案三

把组件库 Vue 的版本更新到最新的,删掉node_modulespackage-lock.json,然后重新npm install安装,接着重新 build 打包,最后在其他项目中就可以使用导出的插件了。

这是我自己的项目的最终的解决方案,也是我自己摸索的,因为走投无路了 hhh,只能祈求官方最新的版本可能会在解决其他 issue 的时候顺带解决了这个 bug。

我自己猜测这个错误可能是因为 Vue 3.4 某些版本的一个 bug,我看了 Vue 官方的 changelog,发现 Vue 3.4.30 更新了一些也回退了一些代码。也能可能是自己 install 的包没有完全更新,或者编译器抽风了 hhh。

一点小小的建议

如果遇到这种官方还没有修复的 bug,自己更过修改版本把 bug 修复了的话,一定要锁版本,因为不锁版本的话,可能后续官方进行更新之后,有些代码和功能会新增或者回退之类的,有可能导致项目无法正常运行。等官方修复了 bug 之后再进行版本更新,关于版本依赖:

符号^:表示主版本(也就是第一位的大版本号)固定的情况下,可更新最新版。例如:vue: “^3.4.29”,3.4.29 及其以上的 3.x.x 都是满足更新要求的。
符号~:表示次版本固定(也就是版本号前两位固定)的情况下,可更新最新版。如:vue: “~3.4.29”,3.4.29 及其以上的 3.4.x 都是满足的。
无符号:无符号表示固定版本号,例如:vue: “3.4.30”,此时一定是安装 3.4.30 版本。也就是锁死版本

总结

本文是我在组件库打包时,遇到的一个插件导出使用报类型错误问题,主要记录自己的解决思路,在此希望对大家有帮助。虽然最终解决了,但是我也没有很明白这个错误应该是什么原因,只能等官方更新版本解决这个问题,或者大家留言讨论讨论,有不对的地方还请多多指教。有收获的话可以点个赞哟。

也许您对下面的内容还感兴趣: