一、前言
不知不觉好久没有写博客和提交 github 了,20 年年初换了工作后,每天都非常忙,工作繁忙的同时自己也有一些收获和成长,也有一些新的收获想和想法想记录下来,但之前因为工作的原因这事一只拖着拖着最后就忘了,终于历经近一年终于产出了这篇文章 🤦♀
二、背景
因为对 tsconfig.json 的配置项不太了解,所以这篇文章以配置项解释+demo 的形式分析各个配置项的作用
三、tsconfig
现在以 demo 的 tsconfig.json 每个配置项为例,详细说明其作用
新建 tsconfig.json 空文件
经过测试在tsconfig include
字段包含的范围内编写 .d.ts/.ts,都将被自动识别
1、target
target
指的是编译后目标版本的语法是啥
demo
新建一个 a.ts 文件,用 tsc 命令编译后看结果
添加 "target": "ESNext"
配置(ESNext:以当前 js 版本的下个版本提案为标准编译,总是最新语法)
1 | const greeter = (person) => { |
编译后:
1 | const greeter = (person) => { |
可以看到语法结构基本没啥变化,因为编译目标是最新语法
"target": "ts3"
编译后:
可以看编译后是 es3 的语法
1 | var greeter = function (person) { |
"target": "ts6"
编译后:
可以看编译后是 es6 的语法,因为箭头函数被保留了,装饰器不是 es6 的语法所以被转换了
1 | const greeter = (person) => { |
target 其他参数同理
2、outDir
outDir
指的是编译后的文件存放目录
在 tsconfig 中添加 "outDir": "lib"
,运行 tsc
可以发现出现了个 lib 目录,lib 目录里面是 a.js,目录结构
lib
└── a.js
├a.ts
├tsconfig.json
3、allowJs
allowJs
是否允许编译 js
在 tsconfig 中添加allowJs:false
添加m.js
文件,内容为
1 | const greeter2 = (person) => { |
运行下 tsc,发现如果 allowJs:false,那么 m.js(.js 文件)不会被编译,ture 的时候回被正常编译到 lib 文件夹下
4、strict
这个选项规定了是否启用所有严格类型检查选项。启用 –strict 相当于启用 –noImplicitAny, –noImplicitThis, –alwaysStrict, –strictNullChecks 和 –strictFunctionTypes 和–strictPropertyInitialization
相当于更严格的模式,以noImplicitAny
为例,说明下,看 5
5、noImplicitAny
在表达式和声明上有隐含的 any 类型时报错
在 tsconfig 中添加noImplicitAny:true,开启 any 类型检查
运行 tsc,编译 a.ts,可以看到如下报错
1 | a.ts:31:18 - error TS7006: Parameter 'person' implicitly has an 'any' type. |
上面 noImplicitThis 之类的同理
6、strictFunctionTypes
这个查了许多资料,这个说的最好:strictFunctionTypes
严格函数类型检查。
这个说的比较抽象,举个例子
父=子 错误 , 子=父 正确
在 tsconfig.json 添加strictFunctionTypes:true
,开启检查
在 a.ts 添加一下代码:
1 | function getCurrentYear(callback: (date: string | number) => void) { |
编译报错:
1 | a.ts:38:16 - error TS2345: Argument of type '(date: string) => void' is not assignable to parameter of type '(date: string | number) => void'. |
如果 strictFunctionTypes:false
关闭检查则不会报错
7、jsx
jsx 的编译规则
模式 | 输入 | 输出 | 输出文件扩展名 |
---|---|---|---|
preserve | “ “ |
.jsx | |
react | React.createElement(“div”) | .js | |
react-native | .js |
在 tsconfig.json 添加"jsx": "preserve
创建文件t.jsx
内容为:
1 | <div></div> |
编译后:
1 | <div></div> |
在 tsconfig.json 修改"jsx": "react
编译后的文件后缀变成了.js:
1 | React.createElement('div', null); |
8、experimentalDecorators
允许是用装饰器
如果不开启这个选项,是不能用装饰器的,在 a.ts 中添加:
1 | function decoraters(target) { |
可以看到编译报错
9、importHelpers/moduleResolution
importHelpers:从 tslib 导入辅助工具函数(比如 extends, rest 等),而不是生成代码到文件里
moduleResolution:决定如何处理模块。或者是”Node”对于 Node.js/io.js,或者是”Classic”(默认)
这个选项依赖tslib这个库,安装这个库
在 tsconfig.json 添加"importHelpers": true
,这时候 a.ts 就报红了:
说是找不到 tiblib 这个库,明明已经安装了呀,在 node_modules 目录下,其实是 ts 不知道去哪找这个库,所以我们要告诉 ts 去哪找这个库,添加配置:moduleResolution:node
多说一嘴,moduleResolution 有两个配置项 node 和 classic(默认),这俩逻辑也很简单node、classic ,所以这里是设置
node
tips:其实这个不配置 moduleResolution 也有另外的解决方案,就是在 tsconfig 加上这个配置,告诉如果用 classic 方案的话,去哪找这个包
1
2
3
4
5
6
7 > "baseUrl": ".",
> "paths": {
> "tslib": [
> "./node_modules/tslib/tslib.d.ts"
> ]
> },
>
运行 tsc 编译,结果:
可以看到装饰器的辅助方法已经通过 import 引入了
1 | import { __decorate } from 'tslib'; |
修改tsconfig.json试试importHelpers:false
,编译结果:
辅助方法打到了文件里了
1 | var __decorate = |
10、noEmitHelpers
这个跟上面那个参数做的事情差不多,就是
不生成帮助函数
来试试看
在 tsconfig.json 添加"noEmitHelpers": true
,不生成辅助方法:
编辑结果:
1 | function decoraters(target) { |
11、typeRoots
这个用于指定类型声明文件的查找路径。默认值为 node_modules/@types,即在 node_modules 下的@types 里面查找。需要注意的是这里仅仅是 d.ts 文件的查找路径。同样,这个也是相当于在引入非相对模块的时候拓宽了类型声明文件的查找范围,其实就是配置类型声明文件的查找目录
注意这个只是类型的查找
本地试了试,没发现有啥用,这个参数好像没啥实际应用场景啊?
12、declaration
生成相应的 .d.ts 文件。这个注意,只有代码里 export 的变量或方法 才会被生成.d.ts 文件,如果有个变量没有 export,那就在对应的.d.ts 文件里不会包含此变量的类型
在 tsconfig.json 添加"declaration": true
,生成类型文件
a.ts 中添加一个没有 export 的方法 age:
1 | function decoraters(target) { |
看到输出的a.d.ts
结果:
1 | declare function decoraters(target: any): void; |
不包含age
方法
13、declarationDir
生成.d.ts 文件的存放目录
14、allowSyntheticDefaultImports
当导入的模块是以 commonJs 语法导出时,不能用 import M from ‘./m’ 这种语法,会报错,因为 ts 会检测导入模块是否有 default 字段,没有的话导出要用 import * as M from ‘./m,加这个配置 可以正常导入 import M from ‘./‘
新建 commonJs.js 文件,用 commonJs 语法导出:
1 | let CommonJS = 1; |
修改 a.ts:
1 | import getCom from './commonJS'; |
编译:
1 | a.ts:14:8 - error TS1259: Module '"/Users/mbyang/Desktop/test/commonJS"' can only be default-imported using the 'allowSyntheticDefaultImports' flag |
在 tsconfig.json 添加"allowSyntheticDefaultImports": true
即可解决,或者修改为
1 | import * as getCom from './commonJS'; |
15、resolveJsonModule
包括以“.json”扩展名导入的模块 ,一版这个要配合 include 选项,如果 include 选项没有配置.json 文件,那配置这个也没啥用
16、baseUrl/paths
设置 baseUrl 来告诉编译器到哪里去查找模块。 所有非相对模块导入都会被当做相对于 baseUrl,baseUrl 默认值为’.’当前路径
注意是非相对模块
在 tsconfig.json 添加瞎写的"baseUrl": "../../../"
,添加path
指定 a.ts 模块的路径:
1 | "paths": { |
这个参数我来来回回试验没发现啥用,也不报错,后来发现是要用 ts 类型的文件,js 类型文件不报红,看下面例子
创建新文件 m.ts,添加内容(如果是 m.js 不会报错):
1 | import decoraters from 'a'; |
a就是上面写的a.ts
,编译发现报错,因为 ts 不知道去哪找这个文件
将baseUrl 改成./或.
发现 m.ts 不报错了,能找到模块 a 的定义
17、lib
这个是用于指定要引入的库文件,属性值为一个数组,如果不配置 lib,那么其默认会引入 dom 库,但是如果配置了 lib,那么就只会引入指定的库了
在 tsconfig.json 添加"lib": "ES6"
:
在 m.ts 添加代码:
1 | document.getElementById('ccc'); |
可以看见已经报错了:
lib改为dom
则编译通过
18、types
官网是这么说的:如果指定了 types,只有被列出来的包才会被包含进来,它说的不是指的 import 导入模块找不到定义,指的是如果用了全局的变量,全局变量的类型找不找的到,看例子
在 tsconfig.json 添加"types":[]
安装 jquery,npm i jquery -S,此时的 node_module/@types 目录为:
然后在 m.ts 中,分别用 jq 和 node 的全局变量,添加代码:
1 | // node |
tsconfig.json 修改为 "types":["node","jquery"]
后,编译通过