TypeScript防脱发级入门——模块化
嗨!大家好!我是法医,一只治疗系前端码猿🐒,与代码对话,倾听它们心底的呼声,期待着大家的点赞👍与关注➕。
TS模块化
1. TS中如何书写模块化
TS中,导入和导出模块,建议统一使用ES6的模块化标准
新建module.ts
文件,导出变量name
和函数numRes
//导出变量name和函数numRes
export const name = "法医";
export function numRes(num1:number,num2:number) {
return num1 + num2;
}
新建index.ts
文件,用于导入name
和numRes
import { name, numRes } from "./myModule";
console.log(name);//输出 “法医”
console.log(numRes(1,2));// 打印 3
在TS中使用模块化是比较简单的,并且我们在导入的时候是不需要自己写import
的,可以利用TS的智能提示,如下:
想要利用TS的智能提示有个前提,那就是在导出文件的时候需要使用普通的导出方式,而不是默认的导出方式,默认导出是没有智能提示的
//普通导出有智能提示
export const name = "法医";
export function numRes(num1:number,num2:number) {
return num1 + num2;
}
//默认导出没有智能提示
export default {
name: "法医",
numRes:function (num1:number,num2:number) {
return num1 + num2;
}
}
还有一个点需要注意,就是在导入模块的时候不要加后缀名ts
,import { name, numRes } from "./myModule.ts";
之所以会报错,是因为导入模块文件会进行编译,如果存在ts后缀名,在编译后的js文件中找不到ts文件的,所以会报错
2. 编译结果的模块化
在TS
中使用模块化,有时会使用ES6模块化
,有时使用CommonJS
模块化,所以也是有必要了解编译后的JS使用的是哪种模块化标准。
首先我们应该清楚一点,关于编译结果中的到底使用哪种模块化是可配置
的,配置文件是tsconfig.json
中的module
属性,它就是用来配置编译后的JS文件是使用哪种模块化标准的
{
"compilerOptions": {//配置编译选项
"target": "es2016",//编译时用的哪一套ES标准
"module": "es6",//配置编译目标使用的模块化标准,commjs是node环境中的标准,es6也可以
"lib": ["ES2016"],//默认是有dom环境的,但现在用不到,这里面是没有node环境配置的,需要安装第三方库
"outDir": "./dist",//将编译的结果放在哪个目录下面
"strictNullChecks": true,//表示更加严格的空类型检查
},
}
使用
ES6标准
对比编译前和编译后es6模块化导出:
由于在TS里面本身使用的是ES6的标准,而对编译结果配置的时候也是ES6的标准,所以从代码来看,两者没有任何区别的,编译结果只是取消了类型约束。
es6模块化导入:
从代码来看使用es6模块导入也是一模一样,没有任何区别的
👉 「小知识:」
从前后编译的结果来看,当TS代码中有注释的时候,编译后的JS文件也是会有注释的,如果不希望注释被编译到结果中,此时可以在
tsconfig.json
进行配置"removeComments": true,//表示移除注释
,配置如下:{
"compilerOptions": {//配置编译选项
"target": "es2016",//编译时用的哪一套ES标准
"module": "es6",//配置编译目标使用的模块化标准,commjs是node环境中的标准,es6也可以
"lib": ["ES2016"],//默认是有dom环境的,但现在用不到,这里面是没有node环境配置的,需要安装第三方库
"outDir": "./dist",//将编译的结果放在哪个目录下面
"strictNullChecks": true,//表示更加严格的空类型检查
"removeComments": true,//表示移除注释
},
}使用
CommonJS
对比编译前和编译后CommonJS模块化导出:
当我们使用commonJs模块化导出的时候,会发现编译后的结果跟编译前有很大差异,在JS文件中会发现第一行是
use strict
严格模式,其实use strict
是没必要出现在编译结果中的,因为我们写的TS代码本身够严格了,因此我们可以进行配置:{
"compilerOptions": {//配置编译选项
"target": "es2016",//编译时用的哪一套ES标准
"module": "CommonJS",//配置编译目标使用的模块化标准,commjs是node环境中的标准,es6也可以
"lib": ["ES2016"],//默认是有dom环境的,但现在用不到,这里面是没有node环境配置的,需要安装第三方库
"outDir": "./dist",//将编译的结果放在哪个目录下面
"strictNullChecks": true,//表示更加严格的空类型检查
"removeComments": true,//表示移除注释
"noImplicitUseStrict": true,//表示编译结果中不包含use strict
},
}接下来我们看这一行代码
Object.defineProperty(exports, "__esModule", { value: true });
这行代码圣骑士相当于exports._esModule = true;
至于有什么作用这里先不说,一会说。CommonJS模块化导入:
在
commonJs
中是没有import..from..
的,它只能通过require
方式导入,在编译后的结果里它会自动声明一个变量,也就是上述代码中的myModule_1
,这个变量是文件名
+"_"
+编号
,如果有多次导入的话,编号会依次自增。在开发过程中很多时候不需要关心导入导出编译的结果是什么,但是了解这个编译结果对处理细节问题上是有帮助的
总结:
有的时候我们会遇到比较特殊的情况,比如说我们想使用
node
里面的fs
,此时会报错,比如说:如果编译结果的模块化标准是ES6:没有区别 如果编结果的模块化标准是commonjs:导出的声明会变成exports的属性,默认导出会变成exports的default属性
3. 解决默认导入的错误
这部分研究在TS
中使用默认导出时产生报错的问题,想要知道什么原因导致的,其实看看编译后的结果也就明白了
从代码中看,fs提示没有默认导出,这里报错的原因是fs
不是通过TS
写的,在fs
模块里面它是通过module.exports = {}
方式导出的,因此导入的时候加一个default
,那肯定是不行的,这时候我们可以这么处理:
之所以会产生这么个问题,是因为有些模块不是我们自己写的,我们自己写直接统一使用ES6模块就可以了,不会有什么问题,但是以前有些模块使用module.exports = {}
方式导出的,这就很尴尬,只能寻找其它解决办法,上述是其中一种办法,但是这种方式不太好,因为fs
对象里面不仅仅只有一个函数,有很多,总不能挨个写一遍把,这肯定是太麻烦了,然而我们可以「导入所有内容,然后起个别名」这种方式处理:
但是对于有强迫症的人来说,我就不想用这种方式,那么还有最后一个办法,在tsconfig.json
中配置"esModuleInterop":true
,意思是启动es模块化交互非es模块导出
{
"compilerOptions": {//配置编译选项
"target": "es2016",//编译时用的哪一套ES标准
"module": "CommonJS",//配置编译目标使用的模块化标准,commjs是node环境中的标准,es6也可以
"lib": ["ES2016"],//默认是有dom环境的,但现在用不到,这里面是没有node环境配置的,需要安装第三方库
"outDir": "./dist",//将编译的结果放在哪个目录下面
"strictNullChecks": true,//表示更加严格的空类型检查
"removeComments": true,//表示移除注释
"noImplicitUseStrict": true,//表示编译结果中不包含use strict
"esModuleInterop":true,//启动es模块化交互非es模块导出
},
}
配置之后,代码不会报错了
4. 在TS中如何使用CommonJs
导入导出
导出:
export = xxx;
//举个栗子
export = {
name:"法医",
sayHello(a:string,b:string){
return a + b;
}
}导入:
import xxx = require("xxx");
//举个栗子
import module = require("myModule");
最后
很感谢小伙伴看到最后😘,如果您觉得这篇文章有帮助到您的的话不妨关注➕+点赞👍+收藏📌+评论📜,您的支持就是我更新的最大动力。