如何让TypeScript默认导出兼容CommonJS模块?
问题
我用TypeScript写了个API封装库,构建后在CommonJS环境里调用构造函数时报错。
代码结构
BattleMetrics.ts类定义:
export default class BattleMetrics { private axios: any; constructor(token: string) { // ... 具体实现 } }
- 主入口
index.ts:
import BattleMetrics from './src/BattleMetrics'; export default BattleMetrics;
报错情况
在TS环境测试完全正常,但写了个CommonJS的test.js:
const BattleMetrics = require('../../dist/index.js') const bm = new BattleMetrics('123')
直接报错TypeError: BattleMetrics is not a constructor,必须改成new BattleMetrics.default('123')才能用。手动改编译后的index.js,把类同时赋值给module.exports就能正常运行,但不想每次手动改。
试过调tsconfig的导出类型没解决,怎么让这个库同时兼容CommonJS和TypeScript?
解决方案
1. 改TS配置(最推荐)
调整tsconfig.json的关键配置,让TS自动处理CommonJS的兼容:
{ "compilerOptions": { "module": "CommonJS", "moduleResolution": "Node", "esModuleInterop": true, "allowSyntheticDefaultImports": true, "target": "ES6", "outDir": "./dist", "declaration": true }, "include": ["src/**/*"] }
esModuleInterop: true:自动生成CommonJS兼容的导出逻辑,require直接拿默认导出,不用加.defaultallowSyntheticDefaultImports: true:配合上面的配置,让TS里的默认导入语法能正常识别CommonJS模块
2. 加双导出
在入口index.ts里同时导出默认和命名导出,覆盖两种模块场景:
import BattleMetrics from './src/BattleMetrics'; export default BattleMetrics; export { BattleMetrics };
编译后CommonJS里可以这么用:
// 两种写法都支持 const BattleMetrics = require('../../dist/index.js').default; // 或者 const { BattleMetrics } = require('../../dist/index.js');
3. 手动加兼容代码
如果上面的配置没效果,直接在入口文件加一段兼容逻辑:
import BattleMetrics from './src/BattleMetrics'; export default BattleMetrics; // 给CommonJS环境做兼容 if (typeof module !== 'undefined' && module.exports) { module.exports = BattleMetrics; module.exports.default = BattleMetrics; }
这样编译后,require拿到的直接就是BattleMetrics类,不用再加.default。
4. 检查package.json
确保package.json里的字段指向正确的编译产物:
{ "main": "./dist/index.js", "types": "./dist/index.d.ts", "type": "commonjs" // 针对CommonJS环境设置,也可以留空让Node自动判断 }
内容的提问来源于stack exchange,提问作者Daniel Wheaton
相关产品推荐
相关产品推荐

