You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript编译为JavaScript后为何与CommonJS require不兼容?

Why TypeScript Compiles export default to exports.__esModule Instead of module.exports

这其实是TypeScript为了兼容ES模块与CommonJS模块互操作性而做的设计,下面给你详细拆解:

核心原因:ES模块 vs CommonJS模块的差异

ES模块(ESM)和CommonJS(CJS)的模块结构本质不同:

  • 在ESM里,每个模块可以有一个default导出,同时还能有多个命名导出;
  • 而在CommonJS里,模块只有一个导出入口——module.exports对象,没有单独的"default"概念。

TypeScript为了让ESM的代码能在CommonJS环境下正常工作,同时也让CommonJS模块能被ESM正确导入,会给编译后的模块添加exports.__esModule = true标记,并将ESM的default导出挂载到exports.default属性上。这个标记是告诉模块加载器:"这是一个从ESM编译过来的模块",从而在导入时正确处理导出内容。

你的代码问题所在

你用纯CommonJS的require()去导入TS编译后的模块时,拿到的是一个包含default属性的对象,而不是直接的函数。所以直接调用greet(...)其实是在调用这个对象,自然无法达到预期效果。

解决方法

这里有几个可行的方案:

1. 在CommonJS文件中手动取default属性

修改你的test.js:

const greet = require("./greet").default;
greet({ name: 'Smith', age: 21 });

2. 在TypeScript中使用CommonJS风格导出

如果你不需要兼容ESM,直接在greet.ts里用CommonJS的导出语法:

module.exports = ({ name, age }) => `Name: ${name}, Age: ${age}`;

这样编译后就会直接生成module.exports = ...,和你预期的一致。

3. 用TypeScript的export =语法

这是TypeScript专门为兼容CommonJS设计的导出方式,修改greet.ts:

export = ({ name, age }) => `Name: ${name}, Age: ${age}`;

编译后同样会生成module.exports = ...的代码,同时也能被ESM的import语法正确导入(前提是你的tsconfig开启了allowSyntheticDefaultImports)。

内容的提问来源于stack exchange,提问作者李鸿章

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:13:11