gpt4 book ai didi

typescript - 了解 tsconfig 文件中的 esModuleInterop

转载 作者:搜寻专家 更新时间:2023-10-30 20:31:41 36 4
gpt4 key购买 nike

我正在检查某个 .tsconfig 文件,在那里我发现了 --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”:true,。我知道它们有点依赖于 "module": "commonjs", 。有人可以尝试用最好的人类语言来解释它吗?

allowSyntheticDefaultImports 状态的官方文档

Allow default imports from modules with no default export. This doesnot affect code emit, just typechecking.

这是什么意思?如果没有任何导出默认值,那么我认为导入默认值的唯一用例是初始化某些东西?像单例?

以下问题/答案也没有意义 Is there a way to use --esModuleInterop in tsconfig as opposed to it being a flag?

以及编译页面上的--esModuleInterop定义

Emit __importStar and __importDefault helpers for runtime babelecosystem compatibility and enable --allowSyntheticDefaultImports fortypesystem compatibility.

对我来说似乎也很难理解/理解

最佳答案

问题陈述

当我们想将 CommonJS 模块导入 ES6 模块代码库时出现问题。

在这些标志之前,我们必须使用 star (* as something) import 导入 CommonJS 模块:

// 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 import 中的命名空间记录(在我们的例子中是 moment)只能是一个普通对象,不可调用(moment() 是不允许的)。

解决方案

通过标记 esModuleInterop,我们可以导入符合 es6 模块规范的 CommonJS 模块。现在我们的导入代码如下所示:

// 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 import 的命名空间,它是默认导入。

但是它是如何工作的呢?如您所见,因为我们进行了默认导入,所以我们在 moment 对象上调用了 default 属性。但是我们没有在 moment 库中的 exports 对象上声明 default 属性。关键是 __importDefault 函数。它将模块 (exports) 分配给 CommonJS 模块的 default 属性:

var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};

如您所见,我们按原样导入 es6 模块,但 CommonJS 模块使用 default 键包装到一个对象中。这使得在 CommonJS 模块上导入默认值成为可能。

__importStar 做类似的工作 - 它返回未修改的 esModules,但将 CommonJS 模块转换为具有 default 属性的模块:

// 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 又如何——它有什么用?现在文档应该很清楚了:

允许从没有默认导出的模块中进行默认导入。这不会影响代码发出,只会影响类型检查。

moment 类型中,我们没有指定默认导出,我们也不应该有,因为它只有在标志 esModuleInterop 开启时才可用。因此,如果我们想从没有默认导出的第三方模块导入默认值,allowSyntheticDefaultImports 将不会报告错误。

关于typescript - 了解 tsconfig 文件中的 esModuleInterop,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56238356/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com