Appearance
11.esModuleInterop
esModuleInterop
和 allowSyntheticDefaultImports
两个选项都是 TypeScript 编译器选项,用于处理 ES6 模块和 CommonJS 模块之间的兼容性问题。它们的主要目的是让 TypeScript 更容易与使用不同模块系统的 JavaScript 代码库进行互操作,但它们的作用和影响有所不同。
相同点
模块兼容性:
- 这两个选项都旨在解决 TypeScript 中 ES6 模块与 CommonJS 模块的兼容性问题,使得开发者可以更方便地导入和使用现有的 JavaScript 库。
启用方式:
- 两个选项都可以单独启用,也可以一起启用。不过,如果启用了
esModuleInterop
,通常不需要再单独启用allowSyntheticDefaultImports
,因为esModuleInterop
已经包含了allowSyntheticDefaultImports
的功能。
- 两个选项都可以单独启用,也可以一起启用。不过,如果启用了
不同点
作用范围:
allowSyntheticDefaultImports
:- 允许从没有默认导出的模块中导入默认导出。这意味着即使模块没有实际的
default
导出,TypeScript 也会假设它有一个,并允许import
语句使用默认导入。 - 主要作用是让 TypeScript 可以更方便地导入 CommonJS 模块,尤其是那些没有明确默认导出的模块。
- 允许从没有默认导出的模块中导入默认导出。这意味着即使模块没有实际的
esModuleInterop
:- 启用所有与模块互操作相关的功能,包括
allowSyntheticDefaultImports
。它的作用不仅仅限于允许默认导入,还包括重新调整 TypeScript 对模块的导入和导出行为,使其更符合 ES6 规范。 - 还会为所有
export =
的模块生成默认导出,确保这些模块在 TypeScript 中可以使用默认导入语法。
- 启用所有与模块互操作相关的功能,包括
编译器行为:
allowSyntheticDefaultImports
:- 只是一个语法上的调整,允许使用默认导入语法,但不改变编译后的输出。
esModuleInterop
:- 改变编译输出,使其与 ES6 模块的行为更加一致。启用这个选项后,TypeScript 编译器会在生成的 JavaScript 代码中添加额外的帮助代码,以模拟 ES6 的模块行为。
示例
假设我们有一个 CommonJS 模块 commonjs-module.js
:
JavaScript
// commonjs-module.js
module.exports = { foo: 'bar' };
1
2
3
2
3
- 只启用
allowSyntheticDefaultImports
:
json
{
"compilerOptions": {
"allowSyntheticDefaultImports": true
}
}
1
2
3
4
5
6
2
3
4
5
6
在 TypeScript 中:
typescript
import commonjsModule from './commonjs-module';
console.log(commonjsModule.foo); // 'bar'
1
2
3
2
3
编译后:
javascript
const commonjs_module_1 = require('./commonjs-module');
console.log(commonjs_module_1.default.foo); // 这里会报错,因为 `commonjs-module.js` 没有 `default` 导出
1
2
3
2
3
- 启用
esModuleInterop
(隐含包含allowSyntheticDefaultImports
):
json
{
"compilerOptions": {
"esModuleInterop": true
}
}
1
2
3
4
5
6
2
3
4
5
6
在 TypeScript 中:
typescript
import commonjsModule from './commonjs-module';
console.log(commonjsModule.foo); // 'bar'
1
2
3
2
3
编译后:
javascript
const tslib_1 = require('tslib');
const commonjs_module_1 = tslib_1.__importDefault(require('./commonjs-module'));
console.log(commonjs_module_1.default.foo); // 正确,因为 `__importDefault` 函数创建了一个默认导出
1
2
3
4
2
3
4
总结
相同点
- 都是用于处理 ES6 模块与 CommonJS 模块的兼容性问题。
- 都能简化从没有默认导出的模块中导入默认导出的操作。
不同点
allowSyntheticDefaultImports
仅仅允许使用默认导入语法,但不改变编译输出。esModuleInterop
不仅允许使用默认导入语法,还会调整编译输出,使其与 ES6 模块行为一致,并包含了allowSyntheticDefaultImports
的功能。
在现代 TypeScript 项目中,通常推荐启用 esModuleInterop
,以便更好地支持模块互操作,并使编译后的代码更符合 ES6 模块规范。