如何创建可选依赖可由应用按需解析的TypeScript工具库
解决方案
这个问题的核心原因是你的工具库用了统一根入口导出所有模块,哪怕应用仅导入无依赖的bar方法,TypeScript 编译时也会加载整个入口对应的类型声明文件,触发对foo模块引入的第三方依赖类型的查找逻辑,才会出现未安装依赖就报错的问题。不需要强制用动态导入,以下是几种可落地的方案:
方案1:拆分子入口(优先推荐,改造成本最低)
不要用单一根index.ts导出所有内容,按照依赖维度拆分独立入口,配合package.json的路径导出配置实现按需引入:
- 调整工具库的打包配置,输出多入口产物,比如无依赖的通用方法打包为
core入口,依赖AWS SDK的方法打包为aws入口 - 在工具库的
package.json中新增以下配置:
{ "exports": { ".": "./dist/index.js", "./core": "./dist/core.js", "./aws": "./dist/aws.js" }, "typesVersions": { "*": { "core": ["./dist/core.d.ts"], "aws": ["./dist/aws.d.ts"] } }, "peerDependenciesMeta": { "@aws-sdk/client-lambda": { "optional": true } } }
- 应用端按需引入对应入口的方法即可:
- 仅用无依赖方法:
import { bar } from 'my-library/core' - 需要用到AWS相关方法:
import { foo } from 'my-library/aws',自行安装对应的peer依赖即可
这种方案不会修改原有业务逻辑,TypeScript 只会加载对应入口的类型声明,完全不会触发未使用模块的依赖类型查找,从根源解决报错。
- 仅用无依赖方法:
方案2:类型层面弱化依赖关联(适合必须保留单入口的场景)
如果必须保留统一根入口,可以调整有第三方依赖的模块的类型写法:
- 所有第三方依赖的导入都用仅类型导入:
import type { Lambda } from '@aws-sdk/client-lambda',避免生成运行时导入代码 - 把依赖第三方类型的参数改写为 inline 导入形式:
export function foo(lambda: typeof import('@aws-sdk/client-lambda')['Lambda']): void { // 原有逻辑 }
- 在
peerDependenciesMeta中把第三方依赖标记为可选,TypeScript 会降低对可选peer依赖的类型检查强度,只要应用端没有实际调用foo方法,就不会抛出依赖不存在的报错。
为什么之前的@ts-ignore方案无效?
你在库源码中添加的@ts-ignore仅会在你编译工具库本身时生效,最终生成的.d.ts文件中仍然保留了对第三方依赖的导入引用,应用编译时会独立解析这些导入路径,自然还会报错。
内容的提问来源于stack exchange,提问作者JHH
相关产品推荐
相关产品推荐

