关于 pnpm monorepo 项目中 TS2742 Error 的 workaround

2024-06-23 22:44

本文主要是介绍关于 pnpm monorepo 项目中 TS2742 Error 的 workaround,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最近我在使用 pnpm 作为包管理器开发一个 monorepo 项目,从个人体验来说,在 monorepo 项目中,pnpm 确实要比 yarn classic 用得舒心,最让我欣喜的是 pnpm 对 workspace 协议的支持度很好;另外感受比较明显的一点就是,开发过程中感知到的由于依赖层级导致的 bug 也变少了。

但是任何事情都不可能是完美的。果不其然,一个关键的 bug 就在等着我。我在这个 pnpm monorepo 项目中尝试为一个子包生成 d.ts 类型声明文件时,出现了一个 TS2742 错误。

error TS2742: The inferred type of 'default' cannot be named without a reference to '.pnpm/@vue+runtime-core@3.3.4/node_modules/@vue/runtime-core'. This is likely not portable. A type annotation is necessary.

从错误信息最后一句话看,是需要加一个类型注解,但是从我的使用场景来看,相关类型应该是能够自动推导出来的,不需要画蛇添足。感觉很奇怪!

第一反应是检查下 .pnpm 目录下的对应的文件是不是都正常。经检查,一切文件结构和软链接都正常。

然后就想着是不是代码引入 vue 相关的依赖时有问题。看了报错处,都是很正常的一些引用,比如:

import { defineComponent } from "vue"

但是从报错信息来看,似乎是找不到 vue 内部的子包的相关类型,难道是通过 vue 找内部包的时候出问题了?

另外很奇怪的一点是:VSCode 表现正常,鼠标悬停类型提示正常,面板也没有报出任何关于类型的错误。

无奈,只能拿着错误信息去 google 搜索,确实找到了 github 上一些关联度很高的 issue,issue 来源包括 typescript, pnpm 等仓库。

microsoft/TypeScript#42873

microsoft/TypeScript#47663

这些 issue 在21年,22年就提出了,但是目前也还没有 Close。我试了 issue 讨论中提到的一些方法,包括修改preserveSymlinks,在项目根目录安装对应依赖,设置 tsconfig.json 中的paths配置辅助 TypeScript 找到对应依赖的位置等,但是最后都没有奏效,可能是我的解决姿势不正确,最终困扰了几天,在 google, stackoverflow, github 上一无所获,也尝试过 debug 去分析代码执行过程,也没看明白。

解决方法1:node-linker=hoisted

于是我在想是不是 pnpm 的依赖结构导致的,如果放弃 symlink 这种方式会不会奏效。结果还真的行,虽然这不是我想要的解决方式,因为这样是完全放弃了 pnpm 的重要优势。

具体做法:

  1. 在 .npmrc 文件中配置node-linker=hoisted
  2. 删除 node_modules 和 pnpm-lock.yaml
  3. pnpm i 重新构建依赖

pnpm

相关链接:node-linker。

解决方法2:依赖提层级 + paths 配置

在使用 node-linker=hoisted 后,我仍然不死心,还是希望能够找到一个更好的方法,能解决问题的同时兼顾 pnpm symlink 的重要特性。

说来也是缘分,前几天,一位圈内好友也遇到了类似问题,并且看到了我在 TypeScript issue 中的 comment,就找到了我讨论这个问题,并分享了他的解决方案。

最终我的解决方法是,将@vue/shared这个包同时安装到 pnpm monorepo 项目的根级 node_modules 下。

pnpm add -Dw @vue/shared

再通过配置 tsconfig.json 中的 paths 配置项,辅助 TypeScript 能够找到对应的依赖。

"paths": {"@vue/shared": ["./node_modules/@vue/shared"]
}

经测试,这个做法必须配置moduleResolutionNode16及以上。

这个解法涉及到的一些关键点其实在一些 issue 中也有提到,不过我之前只是单独采用了 issue 中某一解决方法,而没有把这些方法结合起来尝试,最终导致我没有及时地解决掉这个问题。

具体过程和原因就不分析了,如果有遇到相同问题的朋友,希望能对你有所帮助!

这篇关于关于 pnpm monorepo 项目中 TS2742 Error 的 workaround的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1088485

相关文章

一文教你如何将maven项目转成web项目

《一文教你如何将maven项目转成web项目》在软件开发过程中,有时我们需要将一个普通的Maven项目转换为Web项目,以便能够部署到Web容器中运行,本文将详细介绍如何通过简单的步骤完成这一转换过程... 目录准备工作步骤一:修改​​pom.XML​​1.1 添加​​packaging​​标签1.2 添加

mysql出现ERROR 2003 (HY000): Can‘t connect to MySQL server on ‘localhost‘ (10061)的解决方法

《mysql出现ERROR2003(HY000):Can‘tconnecttoMySQLserveron‘localhost‘(10061)的解决方法》本文主要介绍了mysql出现... 目录前言:第一步:第二步:第三步:总结:前言:当你想通过命令窗口想打开mysql时候发现提http://www.cpp

tomcat多实例部署的项目实践

《tomcat多实例部署的项目实践》Tomcat多实例是指在一台设备上运行多个Tomcat服务,这些Tomcat相互独立,本文主要介绍了tomcat多实例部署的项目实践,具有一定的参考价值,感兴趣的可... 目录1.创建项目目录,测试文China编程件2js.创建实例的安装目录3.准备实例的配置文件4.编辑实例的

springboot集成Deepseek4j的项目实践

《springboot集成Deepseek4j的项目实践》本文主要介绍了springboot集成Deepseek4j的项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录Deepseek4j快速开始Maven 依js赖基础配置基础使用示例1. 流式返回示例2. 进阶

SpringBoot项目启动报错"找不到或无法加载主类"的解决方法

《SpringBoot项目启动报错找不到或无法加载主类的解决方法》在使用IntelliJIDEA开发基于SpringBoot框架的Java程序时,可能会出现找不到或无法加载主类com.example.... 目录一、问题描述二、排查过程三、解决方案一、问题描述在使用 IntelliJ IDEA 开发基于

SpringBoot项目使用MDC给日志增加唯一标识的实现步骤

《SpringBoot项目使用MDC给日志增加唯一标识的实现步骤》本文介绍了如何在SpringBoot项目中使用MDC(MappedDiagnosticContext)为日志增加唯一标识,以便于日... 目录【Java】SpringBoot项目使用MDC给日志增加唯一标识,方便日志追踪1.日志效果2.实现步

Ubuntu中Nginx虚拟主机设置的项目实践

《Ubuntu中Nginx虚拟主机设置的项目实践》通过配置虚拟主机,可以在同一台服务器上运行多个独立的网站,本文主要介绍了Ubuntu中Nginx虚拟主机设置的项目实践,具有一定的参考价值,感兴趣的可... 目录简介安装 Nginx创建虚拟主机1. 创建网站目录2. 创建默认索引文件3. 配置 Nginx4

SpringBoot项目启动错误:找不到或无法加载主类的几种解决方法

《SpringBoot项目启动错误:找不到或无法加载主类的几种解决方法》本文主要介绍了SpringBoot项目启动错误:找不到或无法加载主类的几种解决方法,具有一定的参考价值,感兴趣的可以了解一下... 目录方法1:更改IDE配置方法2:在Eclipse中清理项目方法3:使用Maven命令行在开发Sprin

Nginx实现高并发的项目实践

《Nginx实现高并发的项目实践》本文主要介绍了Nginx实现高并发的项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录使用最新稳定版本的Nginx合理配置工作进程(workers)配置工作进程连接数(worker_co

Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)

《Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)》文章介绍了如何使用dhtmlx-gantt组件来实现公司的甘特图需求,并提供了一个简单的Vue组件示例,文章还分享了一... 目录一、首先 npm 安装插件二、创建一个vue组件三、业务页面内 引用自定义组件:四、dhtmlx