ts-node与Jest的Winston导入行为不一致问题咨询
问题原因分析
核心矛盾在于Winston 2.4.7是纯CommonJS模块,而你的项目通过"type": "module"声明为ES模块,不同工具(ts-node和Jest)对CommonJS模块转ES模块导入的处理逻辑不一致:
1. import winston from 'winston'的表现差异
- ts-node能正常运行:ts-node的ES模块加载器(
ts-node/esm)对CommonJS模块做了兼容处理,会直接把CommonJS的module.exports作为ES模块的默认导出。所以winston变量直接指向Winston的完整导出对象,自然能访问winston.loggers。 - Jest测试失败:Jest 29处理ES模块导入CommonJS时,严格遵循ES模块规范——默认导出对应CommonJS模块的
module.exports.default属性,但Winston 2.4.7的module.exports里根本没有default字段,所以winston变量拿到的是undefined,调用winston.loggers就会报错。
2. import * as winston from 'winston'的表现差异
- Jest测试成功:Jest处理
import * as语法时,会把CommonJS的module.exports整体映射为ES模块的命名导出集合,所以winston变量包含了Winston的全部导出内容,能正常访问winston.loggers。 - ts-node运行失败:ts-node的ES加载器对
import * as语法的处理更严格,它会认为CommonJS模块没有定义ES模块风格的命名导出,因此import * as winston拿到的是一个仅包含__esModule标记的空对象,自然找不到loggers属性。
可选解决方案
可以在tsconfig.json中开启esModuleInterop和allowSyntheticDefaultImports选项,让TypeScript的模块处理逻辑更兼容CommonJS,这样两种导入方式都能在ts-node和Jest下正常工作:
{ "compilerOptions": { "esModuleInterop": true, "allowSyntheticDefaultImports": true } }
内容的提问来源于stack exchange,提问作者Gabriel Furstenheim
相关产品推荐
相关产品推荐

