了解 tsconfig 文件中的 esModuleInterop [英] Understanding esModuleInterop in tsconfig file

查看:37
本文介绍了了解 tsconfig 文件中的 esModuleInterop的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在检查某人的 .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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆