自己网站做问卷调查问卷,临沂做网站的,报考二级建造师证需要什么条件,郑州网站建设九零后Typescript版本
Typescript5.5.2
如果我们使用ESM作为模块系统#xff0c;那么我们经常会用以下两种方式去导入另一个模块#xff1a;
// 引入一个对象#xff0c;包括了所有的export xxx 和 export default
import * as A from ./xx;
// 引入export default
import B fr…Typescript版本
Typescript5.5.2
如果我们使用ESM作为模块系统那么我们经常会用以下两种方式去导入另一个模块
// 引入一个对象包括了所有的export xxx 和 export default
import * as A from ./xx;
// 引入export default
import B from ./xx;
转换为Commonjs的写法为
const A require(xx);
const B require(xx).default;但是实际上这种转换并不是完全对等的因为Commonjs中并没有default实际上大部分模块系统都没有default。这种不对等会导致Typescript编译后的js文件无法正常执行。
问题import X from xx
我们将esModuleInterop设置为false来模拟一下这些问题。
{compilerOptions: {esModuleInterop: false}
}
有如下两个模块分别使用ESM和Commonjs进行导出
// cjs_default.ts
// Typescript的Commonjs导出写法
export {name: 1
}
// esm_default.ts
// ESM导出
export default {name: name
}
然后我们使用ESM来引入这两个模块
import esm from ./esm_default;
import cjs from ./cjs_default;console.log(cjs, esm);
此时编译会报错原因就是我们之前提到的Commonjs没有默认导出
ts/index.ts:2:8 - error TS1259: Module C:/Users/86159/WebstormProjects/\u9762\u8BD5\u9898/ts/cjs_default can only be default-imported using the esModuleInterop flag2 import cjs from ./cjs_default;~~~ts/cjs_default.ts:1:11 export {~~~~~~~~~~2 name: 1~~~~~~~~~~~3 }~This module is declared with export , and can only be used with a default import when using the esModuleInterop flag.Found 1 error in ts/index.ts:2Process finished with exit code 2
这个报错虽然让我们去开启esModuleInterop但是实际上我们只需要将allowSyntheticDefaultImports这个字段设置为true就好了。
现在代码可以正常编译了
// cjs_default.js
// 被正常编译为commonjs模块了
module.exports {name: 1
};// esm_default.js
// 这个exports.__esModule 标识了这个commonjs模块是由ESM模块编译转换的。
Object.defineProperty(exports, __esModule, { value: true });
// module.exports可以省略module
exports.default {name: name
};
// index.js
use strict;
Object.defineProperty(exports, __esModule, { value: true });
var esm_default_1 require(./esm_default);
var cjs_default_1 require(./cjs_default);
console.log(cjs_default_1.default, esm_default_1.default);
我们执行一下生成的js代码但是我们并没有正常的从Commonjs导出的模块中得到正确的结果获得了undefined虽然我们的类型检查通过了代码也编译了但是并没有编译成我们期望的结果。
undefined { name: name }
我们将esModuleInterop设置为true之后代码可以正常编译了我们看一下编译后的文件
// cjs_default.js
// 被正常编译为commonjs模块了
module.exports {name: 1
};// esm_default.js
// 这个exports.__esModule 标识了这个commonjs模块是由ESM模块编译转换的。
Object.defineProperty(exports, __esModule, { value: true });
// module.exports可以省略module
exports.default {name: name
};
// index.js
// 开启esModuleInterop为true会在编译文件中生成这个函数如果在转化import A from xx时调用。
// 对没有default的Commonjs模块系统封装一层通过有没有__esModule字段判断需不需要封装
var __importDefault (this this.__importDefault) || function (mod) {return (mod mod.__esModule) ? mod : { default: mod };
};
Object.defineProperty(exports, __esModule, { value: true });
var esm_default_1 __importDefault(require(./esm_default));
var cjs_default_1 __importDefault(require(./cjs_default));
console.log(cjs_default_1.default, esm_default_1.default); 我们执行一下生成的js代码这次可以正确的输出了
{ name: 1 } { name: name }
问题import * as X from xx
{compilerOptions: {esModuleInterop: true,allowSyntheticDefaultImports: true,}
}
index.ts代码如下
import * as esm from ./esm_default;
import * as cjs from ./cjs_default;console.log(cjs, esm); 编译一直报类型检查的错误报错如下
ts/index.ts:2:22 - error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the esModuleInterop flag and referencing its default export.2 import * as cjs from ./cjs_default;~~~~~~~~~~~~~~~Found 1 error in ts/index.ts:2但是编译后的代码是可以执行的执行结果如下感觉还是有点奇怪的
{ name: [Getter], default: { name: 1 } } { default: { name: name } } 编译后的代码可以看到也是注入了转换函数__importStar 等
use strict;
var __createBinding (this this.__createBinding) || (Object.create ? (function(o, m, k, k2) {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, k2) {if (k2 undefined) k2 k;o[k2] m[k];
}));
var __setModuleDefault (this this.__setModuleDefault) || (Object.create ? (function(o, v) {Object.defineProperty(o, default, { enumerable: true, value: v });
}) : function(o, v) {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 esm __importStar(require(./esm_default));
const cjs __importStar(require(./cjs_default));
console.log(cjs, esm);问题import {x} from xx
index.ts代码如下
import {name
} from ./cjs_default;console.log(name);
会报和import * as X from xx一模一样的错误 但是编译后的代码是可以执行的执行结果如下
use strict;
Object.defineProperty(exports, __esModule, { value: true });
const cjs_default_1 require(./cjs_default);
console.log(cjs_default_1.name); 编译后的代码如下
总结
allowSyntheticDefaultImports
allowSyntheticDefaultImports可以让这种使用ESM模块系统导入default时目标模块系统没有default的类型检查通过只影响类型检查不影响编译结果。
esModuleInterop
esModuleInterop设置为true的时候allowSyntheticDefaultImports如果没有定义会自动跟着设置为true。esModuleInterop会自动注入工具函数将没有default的模块系统封装一层让使用ESM模块系统导入default的结果符合预期。
使用ESM模块系统引入Commonjs模块
方式是否支持备注import X from xx支持import * as X from xx不支持报错能正常编译import {x} from xx不支持报错能正常编译
import * as X from xx这种还有工具函数__importStar 而且官方文档对esModuleInterop的讲解还举了这个例子但是会类型报错很不理解。
如果想解决这个问题有几个方案
1. 使用ts的校验错误忽略ts-ignore。
2. 改写export 为 export使用ESM模块系统
export {name: 1
}// 改写为
const name 1;
export {name
}// 或者改写为
export default {name
}// 或者改写为
export const name 1;
3. 如果是引入的是js文件那可以通过定义d.ts文件避免类型检验错误虽然js中使用的是commonjs模块系统但是d.ts定义成ESM模块系统