TypeScript+Express项目单元测试与编译的导入扩展名冲突问题
TypeScript + Express 单元测试与编译的导入扩展名矛盾问题
我用TypeScript和Express开发应用,补写单元测试时碰到了两个矛盾的要求:
- 运行测试时,.ts文件里的导入语句不需要加.js扩展名
- 编译被测代码时,.ts文件里的导入语句必须加.js扩展名
是不是漏了什么配置?
我的jest.config.js配置
/** @type {import('ts-jest').JestConfigWithTsJest} */ // module.exports = { // preset: 'ts-jest', // testEnvironment: 'node', // }; export default { preset:"ts-jest", testEnvironment:"node", testMatch: [ '**/*.test.ts' // 只执行.test.ts文件 ] }
我的tsconfig.json配置
{ "compilerOptions":{ "target": "es2016", "module": "Node16", "rootDir": "./src", "sourceMap": true, "outDir": "./dist", "removeComments": false, "noEmitOnError": false, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, "skipLibCheck": true } }
已尝试的操作
- 移除.ts文件中的.js扩展名:编译失败
- 尝试将
moduleResolution设置为"bundle":编译器提示该值不合法
解决方案
问题核心在于module: Node16的配置——这个模式要求TypeScript严格遵循Node.js的ESM导入规则,所以必须在导入时添加.js扩展名;但ts-jest默认的处理逻辑未完全适配该规则,导致测试时出现冲突。可以通过以下两种方式解决:
方案1:给测试单独配置TypeScript规则
保持生产编译的Node16模式不变,给jest单独指定一套兼容的ts配置:
- 新建
tsconfig.test.json:
{ "extends": "./tsconfig.json", "compilerOptions": { "module": "CommonJS", "moduleResolution": "Node" } }
- 修改
jest.config.js,指定测试用的tsconfig:
export default { preset: "ts-jest", testEnvironment: "node", testMatch: ['**/*.test.ts'], globals: { 'ts-jest': { tsconfig: './tsconfig.test.json' } } }
这样生产编译用Node16模式(需加.js扩展名),测试用CommonJS模式(无需加.js扩展名),两边均可正常运行。
方案2:让ts-jest适配Node16模式
如果想统一使用Node16模式,可升级依赖并调整jest配置:
- 升级相关依赖:
npm install ts-jest@latest jest@latest typescript@latest --save-dev
- 修改
jest.config.js:
export default { preset: "ts-jest/presets/default-esm", testEnvironment: "node", testMatch: ['**/*.test.ts'], extensionsToTreatAsEsm: ['.ts'], moduleNameMapper: { '^(\\.{1,2}/.*)\\.js$': '$1' }, globals: { 'ts-jest': { useESM: true } } }
同时确保package.json中添加"type": "module",让ts-jest正确处理带.js扩展名的导入,测试时不再报错。
内容的提问来源于stack exchange,提问作者Mariana Arona
相关产品推荐
相关产品推荐

