一般开发用脚手架的话tsconfig.json已经帮我们默认生成好了,不需要去手动配置,所以平时很少去关心这里面配置都代表啥含义,比如我们经常写的一个导入import React from 'react'
, react默认是commonjs
规范导出,那这样写为啥ts中不报错呢?其实这是因为allowSyntheticDefaultImports设置为true的缘故。接下来做一些测试了解下module,allowSyntheticDefaultImports还有esModuleInterop配置都是什么意思。
安装pnpm add typescript @types/node react @types/react
package.json
{
"name": "final-ts-test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"tsc": "tsc --build"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@types/node": "^18.11.9",
"@types/react": "^18.0.25",
"react": "^18.2.0",
"typescript": "^4.8.4"
}
}
准备三个文件,分别是esm.ts, cjs.ts, index.ts
cjs.ts
module.exports = {
cjsA:1,
cjsB:2
}
esm.ts
export default {
esmA: 1,
esmB: 2
};
export const esmC = 3;
index.ts
/** 注释掉import {a} from './cjs'是因为会报ts错,自己写的commonjs的模块没有ts声明文件,
那么用es6的方式导入会报ts错误, 底下react没报错是因为我们引入了@types/react
*/
// import {a} from './cjs'
import esmDefault from './esm'
import * as esAll from './esm'
import { esmC } from './esm'
import React from 'react';
"a".includes("a");
Promise.resolve(4)
console.log(esmDefault) // import default export of esm
console.log(esAll) // import all the export include default from esm
console.log(esmC) // import the varibale from esm
console.log(React);
创建tsconfig.json文件
npx tsc --init
tsconfig.json
{
"compilerOptions": {
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"module": "commonjs", /* Specify what module code is generated. */
"outDir": "./dist", /* Specify an output folder for all emitted files. */
"esModuleInterop": false, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
"strict": true, /* Enable all strict type-checking options. */
"skipLibCheck": true, /* Skip type checking all .d.ts files. */
"allowSyntheticDefaultImports": true,
},
"include": ["src"],
"exclude": [
"node_modules"
]
}
最终的目录结构如下:
接下来观察下tsconfig.json中的配置。
module: 设置为commonjs,代表我们希望tsc编译出来的js代码符合commonjs规范,如果设置为esnext,则说明我们希望tsc编译出来的结果符合esmodule规范(注意: commonjs方式写的模块依然会原样输出,不会被转为esmodule)
allowSyntheticDefaultImports:这个字段的作用只是在静态类型检查时,把 import
没有 exports.default
的报错忽略掉。就比如我们代码中写的import React from 'react'
如果不设置这个字段为true就会报错
点进去React会看到
esModuleInterop: 会真正的在编译的过程中生成兼容代码,使模块能正确的导入(这个只会在module:commonjs模式下生效
)
接下来咱们在上面tsconfig.json的基础上来互相组合这几个配置来做个测试执行npm run tsc
{
"module": "esnext",
"esModuleInterop": true, //这里设置为true或者false对tsc编译的结果没有区别
"allowSyntheticDefaultImports": true,// 一定要设置为true,不然import React from 'react'会报错
}
tsc编译结果原样输出,没有做任何更新
接下来测试
{
"module": "commonjs",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true
}
可以看到esm.js和index.js相比原文件都有了很大的不同
esm.js这个结果跟babel编译后的代码很像
- 设置exports.__esModule = true, 代表源文件是esModule
- 设置exports.default = export default xx
- 设置export.xx = export const xx
index.js这个结果其实跟babel编译后的结果也大同小异
- import * as sth from 'library' = _importStar
- import sth from 'library' = _importDefault
接下来测试
{
"module": "commonjs",
"esModuleInterop": false,
"allowSyntheticDefaultImports": true
}
可以看到没有引入一些helper函数,只是设置了exports.__esModule = true
最后:
一般我们跟webpack结合使用时,将tsconfig.json设置为module:esnext, 就是为了不让typescript处理我们的代码增加一些工具函数方法(就算是设置了esModuleInterop:true也没用,因为moudle:esnext模式下不生效)