如何解决外部项目引用Monorepo组件导出类型时出现多导入路径的问题
解决方案
你遇到的问题本质是打包类型声明时,把内部依赖的common模块也生成了独立的全局模块声明,同时暴露了ComponentA的源码路径导入,可通过以下几种方式优化:
方案1:打平类型声明,合并内部模块
使用支持类型打包的工具(比如rollup-plugin-dts、tsup)开启bundle模式打包类型,工具会自动把内部导入的common类型直接合并到ComponentA的导出模块中,不会生成额外的declare module "common/types"块,最终生成的d.ts只会保留ComponentA的公开导出,示例最终d.ts结构如下:
declare module "ComponentA" { export type Foo = { width: number; height: number; }; // 其他ComponentA的导出内容 }
配置参考(以tsup为例),在ComponentA根目录新建tsup.config.ts:
import { defineConfig } from 'tsup' export default defineConfig({ entry: ['src/main.ts'], outDir: 'dist', dts: true, // 开启类型打包,自动打平内部依赖 clean: true })
方案2:构建后处理d.ts,删除内部模块声明
如果不想换打包工具,可以在ComponentA构建完成后新增一个脚本步骤,直接处理生成的main.d.ts:
- 提取
declare module "common/types"中的所有类型定义 - 将这些类型移动到
declare module "ComponentA/src/main"的导出中 - 删除整个
declare module "common/types"的代码块
处理后d.ts中就不存在common/types的模块声明,自然不会出现对应的导入路径提示。
方案3:禁止内部路径导入,规范导入路径
在ComponentA的package.json中新增exports配置,限制用户只能从包根路径导入:
{ "name": "ComponentA", "version": "1.0.0", "main": "dist/main.js", "types": "dist/main.d.ts", "exports": { ".": { "types": "./dist/main.d.ts", "default": "./dist/main.js" } }, "files": ["dist/*"] }
TypeScript 4.7及以上版本会识别exports配置,不仅会屏蔽common/types的导入提示,也会屏蔽ComponentA/src/main这类内部源码路径的导入,用户只能使用import type { Foo } from 'ComponentA'这种符合语义的导入方式。
方案4:单独发布common公共包
如果common包的类型会被多个组件复用,可以将common包作为独立的Monorepo子包单独发布,命名为@{你的组织名}/common这类规范包名,ComponentA和ComponentB都直接依赖这个公共包,这样类型导入路径会变成import type { Foo } from '@{你的组织名}/common',语义清晰也不会出现路径冲突。
内容的提问来源于stack exchange,提问作者Dennis

