TypeScript 中的多种 import 解义
JavaScript 中有多种 export
的方式,而 TypeScript 中针对这种情况做了多种 import
语法,最常见的就是 import * as path from 'path'
这种。这篇文章主要来讲解 TypeScript 中不同的 import 具有什么意义。
前端开发 QQ 群:377786580
从 export 说起
有很多朋友都问过我关于 TypeScript 中不同 import
的含义,最典型的就是下面的 import
语法:
1 |
|
不少人疑问这句代码究竟是什么意思,这里我们要先从 js 的 export
开始说。
首先,JavaScript 的模块化方案,在历史的演进中,有多种导出模块的方式:exports
、module.exports
、export
、export default
。
在 nodejs 中内置的模块遵循的都是 CommonJS 规范,语法为 module.exports
和 exports
。
1 |
|
例如 nodejs
内置的 events 模块的源码:
在 ECMAScript 6 中又新增了语法 export
和 export default
:
1 |
|
到这里画风还比较正常,而大名鼎鼎的 JavaScript 转码编译器 babel 针对 ECMAScript 6 新增的 export default
语法,搞了个 babel-plugin-transform-es2015-modules-commonjs 的转换插件,用于将 ECMAScript 6 转码为 CommonJs 规范的语法:
源码:
1 |
|
编译后:
1 |
|
到这里,我们看到有三种 export
默认值的语法:
1 |
|
TypeScript 中的 import
在 TypeScript 中,也有多种 import
的方式。
1 |
|
在 tsconfig.json
中,allowSyntheticDefaultImports
会影响到 import 语法的类型检查规则,这个下面再说。
import * as xx from ‘xx’
import * as xx from 'xx'
的语法来一般都是用来导入使用 module.exports
导出的模块。
1 |
|
因为 nodejs 中的模块大部分都是通过 module.exports
、exports.xx
语法进行导出的。
import xx from ‘xx’
默认情况下,import xx from 'xx'
的语法只适用于 ECMAScript 6 的 export default
导出:
模块 foo:
1 |
|
ES6 模块的导入:
1 |
|
而前面我们说了,babel
会将 es6 的模块的 export default
语法编译为 exports.default
语法。
而 TypeScript 默认是不识别这种语法的,如果一个模块的导出是 exports.default
导出,如果使用 import xx from 'xx'
的语法导入是会报错的。
所以在 tsconfig.json
中,有个 allowSyntheticDefaultImports
选项,就是针对这种语法做兼容。
如果设定 allowSyntheticDefaultImports
为 true
,则检测导入的模块是否是 ES6 模块,如果不是,则查找模块中是否有 exports.default
导出。
从而达到针对 exports.default
的兼容。
效果参见这个动画:
我个人是不推荐打开 allowSyntheticDefaultImports
选项的,一般情况下我采取的方式是将 deafult 重新命名:
1 |
|
import xx = require(‘xx’)
import xx = require('xx')
是用来导入 commonjs 模块的库,特殊的地方在于这个库的类型声明是 export = xx
这种方式导出的:
foo.js 源码:
1 |
|
foo.d.ts 类型声明文件源码:
1 |
|
bar.ts 引用:
1 |
|
我在 《JavaScript 和 TypeScript 交叉口 —— 类型定义文件(*.d.ts) 》中讲述过 TypeScript 类型声明文件对导入导出的影响。
const xx = require(‘xx’)
当一个模块没有类型声明文件的时候,可以使用 commonjs 原始的 require()
方式来导入模块,这样会默认该模块为 any。
总结
最后我们整体总结下,在 TypeScript 中,有多种 import 的方式,分别对应了 JavaScript 中不同的 export。
1 |
|
针对 babel
编译出来的 exports.default
语法,ts 提供了 allowSyntheticDefaultImports
选项可以支持,只不过个人不太推荐。
个人建议将 default
重命名。
1 |
|
关于 TypeScript 中类型声明文件(*.d.ts) 对 import 和 export 的影响,可以参考我之前写的 《JavaScript 和 TypeScript 交叉口 —— 类型定义文件 》。
前端开发 QQ 群:377786580