前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vue3和@types/node的类型不兼容问题

Vue3和@types/node的类型不兼容问题

作者头像
Tusi
发布2022-11-23 14:47:15
1.4K0
发布2022-11-23 14:47:15
举报
文章被收录于专栏:前端司南前端司南前端司南

原创@前端司南

插播个广告:最近我在掘金社区有个专栏,主要涉及Vite,Vue3,TypeScript,业务组件库等关键词,目的是帮助读者掌握基于 Vite 构建现代组件库的核心方法。 链接:https://juejin.cn/column/7140103979697963045

最近有个新项目启动,主体内容与先前做的一个项目相似度很高,于是我准备拿这个旧项目作为模板简单改改,就可以启动新项目的开发了。

先说说现状,为了更好地拥抱云原生,部门内部的构建方案进行过升级,目前采用的是 Buildpacks 构建项目镜像,并且相关的服务器架构也做了调整,打镜像的 Runner 是部署在内网的,没有外网通道,也就是说安装 npm 依赖时必须从企业私有的 Nexus NPM 代理走

带来的问题就是:这个旧项目启动时还是采纳的旧版镜像构建方案,并不存在新版镜像构建方案带来的内网限制。而现在要基于这个旧项目开发新项目,对接的相关环境都是采纳的新方案,如果不将 npm registry 调整为私有的 Nexus NPM 代理,构建镜像这一步就没法走下去。

所以我就必须得先把 npm registry 调整一下,重新生成 lock 文件。

.npmrc修改成如下(已去掉敏感信息):

registry=https://nexus.xxx.tech:8443/repository/npm-group/
always-auth=true
_auth=xxGxxxxxxxxxxyQ0xxlGxmc=

yarnrc也修改一下:

registry "https://nexus.xxx.tech:8443/repository/npm-group/"

npm-group 包含了 npm-proxy 和 npm-hosted,从这里既可以下载通过 npm-proxy 代理过来的公开发行的 npm 包,也可以下载通过 npm-hosted 维护的企业内部私有的 npm 包。

这个项目用的是 Yarn,所以我接着删掉 yarn.lock 重新生成 lock 文件。

此时最好参照旧的 lock 文件,将关键依赖的版本号先锁住,再重新生成新的 lock 文件,防止在 ~, ^ 这种约束不强的规则下,最终安装的依赖版本号发生变化的情况。

生成完 lock 文件后,检查一下 dev 和 build 等场景,是不是基本上没什么问题。不出意外的话,就要出意外了!

很快,我就在一段 tsx 代码上遇到了这么一个报错:

Type '() => void' is not assignable to type 'MouseEvent'.ts(2322)
runtime-dom.d.ts(1401, 3): The expected type comes from property 'onClick' which is declared here on type 'IntrinsicAttributes & AntdIconProps'

这个报错是从 runtime-dom.d.ts 中抛出来的,我第一反应就是看看@vue/runtime-dom这个包的版本是不是变了。

查了一下发现,@vue/runtime-dom确实是变了,从3.2.33变成了3.2.40

而这个变化是由于vue的版本号变化引起的,这是因为我的vue版本约束是~3.2.29,重新生成 lock 文件时会检查有没有较新的版本。

好,那我就锁vue的版本号,就定为原来生成的3.2.33版本。

"vue": "3.2.33",

重新安装依赖,期待能解决问题。

但是这并没有解决问题,报错依然存在。于是我尝试去锁可能影响这个问题的一些依赖的版本号,包括typescript, @typescript-eslint/eslint-plugin, @vue/eslint-config-typescript 等等,最终都没有解决这个问题,搞了个把小时,emo了...

于是,我就尝试找问题源runtime-dom.d.ts有没有什么问题,先仔细观察下报错信息,

The expected type comes from property 'onClick' which is declared here ...

既然你说 onClick 未声明,那我把 onClick 设置为可选的行不行?

// node_modules/@vue/runtime-dom/dist/runtime-dom.d.ts

export interface Events {
  // ...
  onClick?: MouseEvent;
  // ...
}

改了之后这个报错还真的消失了!!!

但是直接改 node_modules 里的代码肯定是不行的,离开自己的机器,就没法同步到这个修改。

借助 patch-package 可以实现修改 node_modules 后也能让其他人安装时同步到修改信息这种能力,但是我还不想这么做,能不能在项目中加一个d.ts,把这个interface修改一下呢?

考虑到interface有合并能力,我先尝试在global.d.ts中加同名的interface Events

declare interface Events {
    onClick?: MouseEvent;
}

但是发现也并没有作用,因为runtime-dom.d.ts中用了export interface Events,这意味着Events接口是模块下的,我这样直接加在全局是合并不了的,那有没有办法合并模块下的interface呢?

我简单尝试了一下declare一个同名的module,然后加入一个interface Events,也不行,这样就直接覆盖了node_modules里的类型声明。

最后实在没办法了,我想到:既然覆盖了,那就全部覆盖吧!我干脆把node_modules/@vue/runtime-dom/dist/runtime-dom.d.ts整个文件抄了出来,就改了onClick?: MouseEvent;这一行,效果确实可以,这个问题算是临时解决了。

福无双至,祸不单行,我就知道事情没这么简单!

继续往下测试,我又遇到一个报错:

这真的是搞心态啊,@ant-design/icons-vue不报错了,div又报错了。

收拾好心情,发现 VSCode 右下角出现了一个提示信息。

打开一看,终于找到了问题原因,这是 Volar 给出的提示。

原来是@types/node@18.8.4版本与vue@3.2.40版本不兼容,会造成模板中的 DOM event type 出错,解决的方法有两个:

  1. 降低@types/node版本至18.8.0
  2. 升级 Vue 的版本号至3.2.41,后面还备注了(如果已发行)。

于是,我去看了一下 Vue 的最新版本,发现 3.2.41 还没有发布,可能也正在解决这个问题吧!

那就选择降低@types/node的版本号吧,最终解决了这个问题,前面改的那个interface相关的代码也可以删了。

相关 issue 还是 2 天前提出的,说明这个问题还蛮新的。

为啥 Volar 不早点提示我呢?难道是因为我第一个报错是在.tsx中?估计是...

END

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-10-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 bin不懂二进制 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档