0
点赞
收藏
分享

微信扫一扫

tsconfig之esModuleInterop属性


背景

如下代码

import fs from 'fs';

fs.copyFile('');

当 ​​esModuleInterop​​​ 为 ​​false​​​ 时,​​typescript​​​ 提示报错如下 ​​TS1192: Module '"fs"' has no default export.​

为什么会出现这种报错呢,因为 ​​fs​​​ 模块的确没有默认导出。因为 ​​fs​​​ 是遵循 ​​cjs​​ 规范写的。即类似于这种导出:

module.exports = fs = {
copyFile,
copyFileSync,
}

如何解决

方案一

使用如下方式导入 ​​fs​​ 包

import * as fs from 'fs'

fs.copyFile('');

可以看下两种不同的导入方式编译后的结果

编译前

import fs from 'fs';
import * as fsBak from 'fs';

fs.copyFile('', '', () => {});
fsBak.copyFile('', '', () => {});

编译后

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = require("fs");
const fsBak = require("fs");
fs_1.default.copyFile('', '', () => { });
fsBak.copyFile('', '', () => { });

看到编译后的结果可以发现使用 ​​import fs from 'fs';​​​ 进行导入的,最终编译调用方法时,会从 ​​default​​​ 属性中去调用方法,
因为 ​​​import​​​ 的默认导入认为模块的导出是使用 ​​export default​​​ 进行的。但如果是 ​​commonjs​​​ 模块它们并不是这样的。
所以 ​​​fs_1.default.copyFile​​ 是不存在的。

方案二

开启 ​​esModuleInterop​​​ 为 ​​true​

编译前

import fs from 'fs';

fs.copyFile('', '', () => {});

编译后

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
fs_1.default.copyFile('', '', () => { });

可以看出 ​​typescript​​​ 生成了一个 ​​__importDefault​​​ 函数,它的作用是:
如果目标模块是 ​​​esm​​​,就直接返回目标模块;否则将目标模块挂在一个对象的 ​​default​​ 上,返回该对象

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

编译前

import * as fsBak from 'fs';

fsBak.copyFile('', '', () => {});

编译后

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function (o, m, k,) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function () { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function (o, m, k,) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function (o,) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function (o,) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const fsBak = __importStar(require("fs"));
fsBak.copyFile('', '', () => { });

可以看出 ​​typescript​​​ 生成了一个 ​​__importStar​​ 函数,它的作用是:

  • 如果目标模块是​​esm​​,就直接返回目标模块
  • 否则将目标模块上所有的除了​​default​​​ 以外的属性挪到​​result​​ 上
  • 将目标模块自己挂到​​result.default​​ 上

总结

​esModuleInterop​​​ 选项的作用是支持使用 ​​import cjs from 'cjs'​​​ 的方式引入 ​​commonjs​​ 包。


举报

相关推荐

0 条评论