了解 tsconfig 文件中的 esModuleInterop [英] Understanding esModuleInterop in tsconfig file
问题描述
我正在检查某人的 .tsconfig
文件,在那里我发现了 --esModuleInterop
I was checking out someone .tsconfig
file and there I spotted --esModuleInterop
这是他的.tsconfig
文件
{
"compilerOptions": {
"moduleResolution": "node",
"target": "es6",
"module": "commonjs",
"lib": ["esnext"],
"strict": true,
"sourceMap": true,
"declaration": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"declarationDir": "./dist",
"outDir": "./dist",
"typeRoots": ["node_modules/@types"]
},
"include": ["src/**/*.ts"],
"exclude": ["node_modues"]
}
在这里,我的主要问题是什么是 "esModuleInterop": true,
和allowSyntheticDefaultImports":真,
.我知道它们有点依赖于 "module": "commonjs",
.有人可以尝试用最好的人类语言来解释它吗?
Here, My primary question is what is "esModuleInterop": true,
and
"allowSyntheticDefaultImports": true,
. I know they are sort of dependent on the "module": "commonjs",
. Can someone try to explain it in the best human language possible?
allowSyntheticDefaultImports
的官方文档说明
允许从没有默认导出的模块中默认导入.这确实不影响代码发出,只是类型检查.
Allow default imports from modules with no default export. This does not affect code emit, just typechecking.
这是什么意思?如果没有任何导出默认值,那么我认为导入默认值的唯一用例是初始化某些东西?像单身?
What does that mean? If there isn't any export default then I think the only use case of the import default would be to initialize something? Like a singleton?
以下问题/答案也没有意义有没有办法在 tsconfig 中使用 --esModuleInterop 而不是标志?
The following question/answer does not make sense as well Is there a way to use --esModuleInterop in tsconfig as opposed to it being a flag?
和--esModuleInterop
在编译器页面上的定义
And --esModuleInterop
definition on the compiler page
为运行时 babel 发出 __importStar 和 __importDefault 助手生态系统兼容性并启用 --allowSyntheticDefaultImports类型系统兼容性.
Emit __importStar and __importDefault helpers for runtime babel ecosystem compatibility and enable --allowSyntheticDefaultImports for typesystem compatibility.
我似乎也很难理解/理解
Also seemed difficult for me to understand/comprehend
推荐答案
问题说明
当我们想要将 CommonJS 模块导入 ES6 模块代码库时会出现问题.
Problem statement
Problem occurs when we want to import CommonJS module into ES6 module codebase.
在这些标志之前,我们必须使用 star (* as something
) import 导入 CommonJS 模块:
Before these flags we had to import CommonJS modules with star (* as something
) import:
// node_modules/moment/index.js
exports = moment
// index.ts file in our app
import * as moment from 'moment'
moment(); // not compliant with es6 module spec
// transpiled js (simplified):
const moment = require("moment");
moment();
我们可以看到 *
在某种程度上等同于 exports
变量.它运行良好,但不符合 es6 模块规范.在规范中,star 导入中的命名空间记录(在我们的例子中为 moment
)只能是一个普通对象,不可调用(moment()
是不允许的).
We can see that *
was somehow equivalent to exports
variable. It worked fine, but it wasn't compliant with es6 modules spec. In spec, the namespace record in star import (moment
in our case) can be only a plain object, not callable (moment()
is not allowed).
使用标志 esModuleInterop
,我们可以导入符合 es6
模块规范的 CommonJS 模块.现在我们的导入代码如下所示:
With flag esModuleInterop
we can import CommonJS modules in compliance with es6
modules spec. Now our import code looks like this:
// index.ts file in our app
import moment from 'moment'
moment(); // compliant with es6 module spec
// transpiled js with esModuleInterop (simplified):
const moment = __importDefault(require('moment'));
moment.default();
它可以工作并且完全适用于 es6 模块规范,因为 moment
不是来自 star 导入的命名空间,而是默认导入.
It works and it's perfectly valid with es6 modules spec, because moment
is not namespace from star import, it's default import.
但是它是如何工作的呢?如您所见,因为我们执行了默认导入,所以我们在 moment
对象上调用了 default
属性.但是我们没有在 moment 库中的 exports
对象上声明 default
属性.关键是 __importDefault
函数.它将模块 (exports
) 分配给 CommonJS 模块的 default
属性:
But how does it work? As you can see, because we did a default import, we called the default
property on a moment
object. But we didn't declare a default
property on the exports
object in the moment library. The key is the __importDefault
function. It assigns module (exports
) to the default
property for CommonJS modules:
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
如您所见,我们按原样导入 es6 模块,但 CommonJS 模块使用 default
键包装到一个对象中.这使得在 CommonJS 模块上导入默认值成为可能.
As you can see, we import es6 modules as they are, but CommonJS modules are wrapped into an object with the default
key. This makes it possible to import defaults on CommonJS modules.
__importStar
做类似的工作 - 它返回未触及的 esModules,但将 CommonJS 模块转换为具有 default
属性的模块:
__importStar
does the similar job - it returns untouched esModules, but translates CommonJS modules into modules with a default
property:
// index.ts file in our app
import * as moment from 'moment'
// transpiled js with esModuleInterop (simplified):
const moment = __importStar(require("moment"));
// note that "moment" is now uncallable - ts will report error!
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
合成进口
那 allowSyntheticDefaultImports
怎么样——它有什么用?现在文档应该很清楚了:
Synthetic imports
And what about allowSyntheticDefaultImports
- what is it for? Now the docs should be clear:
允许从没有默认导出的模块中默认导入.这不影响代码发出,只是类型检查.
在 moment
类型中,我们没有指定默认导出,我们也不应该有,因为它只有在标志 esModuleInterop
开启时才可用.所以allowSyntheticDefaultImports
如果我们想从没有默认导出的第三方模块导入默认值就不会报错.
In moment
typings we don't have specified default export, and we shouldn't have, because it's available only with flag esModuleInterop
on. So allowSyntheticDefaultImports
will not report an error if we want to import default from a third-party module which doesn't have a default export.
这篇关于了解 tsconfig 文件中的 esModuleInterop的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!