TypeScript+ESM+ts-jest环境下transformIgnorePatterns失效求助
在使用 TypeScript、ESM、npm workspaces 搭配 ts-jest 时,遇到 transformIgnorePatterns 无法正常转译 node_modules 中的 ESM 包(如 picocolors、chalk),报错提示 Cannot use import statement outside a module,临时修改 node_modules 代码并非长久之计,可通过以下配置调整解决问题:
核心问题分析
项目启用 ESM(package.json 设 "type": "module")后,jest 对模块的处理逻辑与 CommonJS 不同,默认会跳过 node_modules 转译,但部分第三方包仅提供 ESM 格式,需要显式配置让 ts-jest 处理这些包;同时 npm workspaces 的路径结构也会影响正则匹配的准确性。
具体解决方案
1. 修正 ts-jest 转译配置,启用 ESM 支持
在 jest.config.ts 中给 ts-jest 显式开启 ESM 支持,同时调整 transformIgnorePatterns 的正则匹配规则适配 workspace 路径:
export default { preset: 'ts-jest/presets/default-esm', testEnvironment: 'node', testMatch: ['**/*.spec.ts'], transform: { '^.+\\.tsx?$': ['ts-jest', { useESM: true }] // 显式启用ESM模式 }, // 精确匹配需要转译的包,适配npm workspaces路径结构 transformIgnorePatterns: ['<rootDir>/node_modules/(?!log-symbols|picocolors)'], // 处理ESM导入的扩展名问题(TypeScript编译后可能带.js后缀,jest需要映射) moduleNameMapper: { '^(\\.{1,2}/.*)\\.js$': '$1' }, // 告知jest将.ts文件视为ESM模块 extensionsToTreatAsEsm: ['.ts'] };
2. 优化 TypeScript 模块解析配置
修改 tsconfig.json 的 moduleResolution 为 node16 或 nodenext,这两个模式对 ESM 和 CommonJS 混合模块的解析更准确:
{ "compilerOptions": { "target": "ES2022", "module": "ESNext", "moduleResolution": "node16", // 替换原node模式 "declaration": true, "strict": true, "incremental": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "composite": true, "types": ["node", "jest"], "allowImportingTsExtensions": true, "allowJs": true, "noEmit": true, "resolveJsonModule": true }, "ts-node": { "esm": true }, "exclude": ["node_modules"] }
3. npm workspaces 多包适配
如果是多包 workspace 结构,子包的 jest.config.ts 可继承根配置并指定自身 rootDir,避免路径匹配错误:
import rootConfig from '../jest.config.ts'; export default { ...rootConfig, rootDir: __dirname };
4. 更新依赖版本
确保 jest、ts-jest、typescript 为最新版本,旧版本可能存在 ESM 兼容 bug:
npm update jest ts-jest typescript
内容的提问来源于stack exchange,提问作者Mateusz Kućka

