如果你使用 TypeScript,不要忘记启用 `"esModuleInterop": true` 和 `"allowSyntheticDefaultImports": true` 以获得更好的开发体验。这两个配置项的作用是什么
这两个 TypeScript 配置项对于使用 CommonJS 模块和 ES 模块的互操作性非常重要,特别是在使用像 axios 这样的库时。让我详细解释它们的作用:
esModuleInterop
作用
启用 ES 模块与 CommonJS 模块之间的互操作性。
背景
在 JavaScript 中有两种主要的模块系统:
- CommonJS (CJS):Node.js 使用的模块系统,使用
require()和module.exports - ES 模块 (ESM):JavaScript 官方标准,使用
import和export
解决的问题
默认情况下,TypeScript 对这两种系统的互操作支持有限。例如,当你导入一个 CommonJS 模块时:
// axios 是一个 CommonJS 模块
import axios from 'axios'; // 没有启用 esModuleInterop 时可能会有问题
启用 esModuleInterop 后,TypeScript 会在编译时创建辅助函数,使 CommonJS 模块在 ES 模块环境中表现得像原生 ES 模块。
编译前后对比
不启用 esModuleInterop 时:
import axios from 'axios'; // 可能导致运行时错误
编译为:
const axios = require('axios'); // 可能不符合预期
启用 esModuleInterop 后:
import axios from 'axios'; // 正常工作
编译为:
const axios = tslib_1.__importDefault(require('axios')); // 正确处理默认导出
allowSyntheticDefaultImports
作用
允许对没有明确设置默认导出的模块进行默认导入。
解决的问题
许多 CommonJS 模块(如旧版本的 axios)没有明确的 export default,但你仍可能想用 import library from 'library' 的语法导入它们。
使用示例
不启用 allowSyntheticDefaultImports 时:
// 对于没有默认导出的模块,必须这样做
import * as axios from 'axios'; // 命名空间导入
const axiosInstance = axios.default || axios; // 还要处理 default 属性
启用 allowSyntheticDefaultImports 后:
// 可以直接使用默认导入,即使模块没有默认导出
import axios from 'axios'; // 简洁明了
两者结合使用
这两个选项通常一起使用,因为它们共同解决了 ES 模块和 CommonJS 模块之间的互操作问题:
{
"compilerOptions": {
"esModuleInterop": true,
"allowSyntheticDefaultImports": true
}
}
这样配置后,你可以统一使用现代的 ES 模块导入语法,无论底层库是使用哪种模块系统编写的:
import axios from 'axios'; // 即使 axios 是 CommonJS 模块也能正常工作
import { useState } from 'react'; // 对原生 ES 模块也能正常工作
import cacheAdapterEnhancer from './cacheAdapterEnhancer'; // 对你自己的模块也正常工作
为什么在使用 axios 时特别重要?
-
axios 是 CommonJS 模块:axios 主要为 Node.js 环境设计,使用 CommonJS 模块系统
-
TypeScript 默认行为:默认情况下,TypeScript 对 CommonJS 模块的处理可能不符合现代前端开发习惯
-
代码一致性:启用这些选项后,你可以在整个项目中使用一致的
import语法,而不需要为某些库使用特殊的导入方式
这两个配置让 TypeScript 编译器处理模块导入时更加智能,使开发者可以专注于业务逻辑而不是模块系统的差异。

浙公网安备 33010602011771号