我们都知道ts不能直接放在浏览器中,但是js可以
每一个ts要执行tsc .ts文件
但是一旦ts文件一多,一个一个编译太麻烦了,所以:
编译选项
自动编译文件
- 编译文件时,使用
-w指令后,TS编译器会自动监视文件的变化,并在文件发生变化时对文件重新编译。 - 示例tsc xxx.ts -w
tsc xxx.ts -w
- 编译文件时,使用
自动编译整个项目
- 如果直接使用
tsc指令,则可以自动将当前项目下的所有ts文件编译为js文件。 - 但是能直接使用
tsc命令的前提时,要先在项目根目录下创建一个ts文件tsconfig.json(tsconfig.json是ts编译器的一个编译文件,ts编译器可以根据它的信息来对代码进行编译) tsconfig.json是一个json文件,添加配置文件后,只需tsc命令即可完成对整个项目的编译配置选项:
include(包含)
- 定义希望被编译文件所在的目录
- 默认值:[“*/“]
示例:
"include":["src/**/*","test/**/*"]
上述示例中,所有src目录和test目录下的文件都会被编译
exclude
- 定义需要排除在外的目录
- 默认值:[“node_modules”,”bower_components”,”jspm_packages”]
示例:
"exclude":["./src/hello/**/*"]
配置文件的作用就是来配置我们这个ts的一些编译信息的,它会根据编译信息根据来进行编译
- 如果直接使用
创建tsconfig.json
{"compilerOptions": {"module": "commonjs","target": "ES5","sourceMap": true},"exclude":["node_modules"]}
你也可以:
{}
有了tsconfig.json文件,你直接执行tsc就可以执行所有的ts文件
这个默认是编译所有ts文件,但是我们在真正开发过程中不是所有的ts都是要经过编译的。
include(主要记住)
包含
{/*include:包含就是来指定哪些ts文件需要被编译*/"include":["./src/**/*",// ./src/**/* | *:表示任意文件 | **:表示任意的目录]}
创建/src目录,在下面添加app.ts
let a: number|String = 1console.log(a);
执行tsc发现只对src下的文件编译成js,文件外的ts没有编译成js
include表示指定我们要编译的文件
exclude
不包含
{"include":[...],"exclude":[]}
有一些文件即便是在包含的src里面,但是我们不希望被编译的,就可以用exclude进行排除,怎么写?
{"include": [...],//包含的目录里的所有文件进行ts编译"exclude": ["./src/hello/**/*"],//表示我除了hello下的文件}
默认要排除的文件是这些:
- node_modules
- bower_components
- jspm_packages
exclude表示不需要被编译的文件目录
extends
继承:说白了就是**当我们的配置文件特别复杂的时候,而且不想重复写**
有**tsconfig.json**和**xxx.json**,我想把**xxx.json**放入**tsconfig.json**,但是我又不想再在写一遍,就可以用**extends**去继承一下。就像是我们引入一个外部文件是一样的
示例:
{"include": [...],//包含的目录里的所有文件进行ts编译"exclude": [...],//表示哪些文件不进行ts编译"extends": "./configs/base"}
files
文件
指定被编译文件的列表,只有需要编译的文件少时才用到
示例:
{"include": [...],//包含的目录里的所有文件进行ts编译"exclude": [...],//表示哪些文件不进行ts编译"extends": "./configs/base",//引入外部配置"files": ["core.ts","sys.ts",...],}
compilerOptions(最最重要)
编译器的选项
{..."compilerOption":{},}
里面有很多的子选项:
target
目标
target用来指定ts被编译的版本
最明显的是
ts:
let a:number = 1;
经过tsc编译为js的时候let就被编译为var:
var a = 1;
就是因为是默认情况下ts会转换成es3版本的js。为什么转换成es3?
因为es3比较老,但是它兼容性比较好,所有浏览器都支持
修改es版本
{..."compilerOption":{"target": "ES6"}}
这时候会发现ts里面是let a,js里面也是let a
target里面能写的就是es的版本
如果不知到写什么,有一个办法:
就是不知道版本瞎写
{..."compilerOption":{"target": "abc"}}
使用tsc编译的时候就会报错:
Argument for '--target' option must be: 'es3', 'es5', 'es6', 'es2015', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'esnext'.
里面就是target里面能接收到的值
module
模块
最开始的js是没有模块化的概念,但是后来js对它进行模块化的拓展加强以至于后来es6都有了自己的模块化,就导致在js中有着各种各样的不同版本模块化的解决方案。所以最终你想要编译的js是哪种模块化的解决方案?
通过module来设置
module:就是来指定使用的模块化的规范
先随便写:
{..."compilerOption":{"target": "ES6","module": "abc",}}
然后,整一个模块化的ts文件:
//导出内容export const hi:string = "你好";
然后在app.ts里面导入这个模块:
import {hi} from './m.js'let a: number|String = 1console.log(a);
报的错:
Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015', 'es2020', 'es2022', 'esnext', 'node12', 'nodenext'.
所以我们改tsconfig.json
{..."compilerOption":{"target": "ES6","module": "ES6",}}
let a = 1;console.log(a);export {};
由于我的hi没有使用,所以在./src/app.js里面看不到那个hi
所以我们打印一下:
import {hi} from './m.js'let a: number|String = 1console.log(a);console.log(hi)
重新编译:
import { hi } from 'm.js';let a = 1;console.log(a);console.log(hi);
这里就使用了es6的模块化标准
lib
lib(library):用来指定项目中使用的库
我们一般情况下是不动它的。
因为像js会用到很多第三方库: 比如我们经常操作的DOM(document)
lib表示来指定你的项目里面想要用到哪些库
没有lib:document有提示信息;有lib:document就没有提示信息了
若是有lib但是你还想用DOM,可以:
{..."compilerOptions": {"target": "ES6","module": "ES6","lib": ["DOM"]}}
所以lib一般情况下我们不需要改,什么时候需要动他?
我的代码不是在浏览器的环境中运行的,而是在nodejs环境中运行,里面没有dom,那你可以去修改它
lib我可以填哪些东西?
{..."compilerOptions": {"target": "ES6","module": "ES6","lib": ["xxx"]//随便写一个}}
重新编译:
Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'esnext', 'dom', 'dom.iterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2020.bigint', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'esnext.array', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref'.
一般情况下不用动它
lib:指定浏览器当中所要指定的一个库。默认允许的环境就是我们浏览器所需要的运行环境
outDir
include:哪些文件夹里面的代码需要被我们es编辑器所解析,解析完后在哪呢?
有些时候我不希望ts文件和js文件在一起
我们就会设置一个目录去放编译后的文件,这就是我们outDir的作用**outDir**: 用来指定编译后文件所在的目录
{..."compilerOptions": {"target": "ES6","module": "ES6","outDir": "./dist"}}
outFile(了解)
我们输出的文件**outFile**: 将我们的代码合并为一个文件
修改m.ts和app.ts
app.ts
let a: number|String = 1console.log(a);
m.ts
let b:number = 20let c:string = 'hello'console.log(b,c)
tsconfig.json
{..."compilerOptions": {"target": "ES6","module": "ES6","outDir": "./dist","outFile": "./dist/app.js"}}
就是说,我要把代码合并到app.js当中
在运行前先把dist目录先删了
现在我们再执行以下编译tsc
会有报错,先不看报错,看dist文件目录下只有一个app.js
设置**outFile**后,所有的全局作用域中的代码会合并到同一个文件中
如果将ts中的模块化整上,你就整不上了
Only 'amd' and 'system' modules are supported alongside --outFile.
意思是:如果你想要把多个模块给它合并成一个文件,你必须使用模块化规范,必须是amd或者system
{..."compilerOptions": {"target": "ES6","module": "system","outDir": "./dist","outFile": "./dist/app.js"}}
我们在这里用的不多。因为这个不灵活,实际上这种应该结合打包工具去使用的
allowJs
allow:允许,js:js
{..."compilerOptions": {"target": "ES6","module": "ES6","outDir": "./dist",//是否对我们js文件进行编译,默认是false"allowJs": false}}
在我们src目录下创建hello.js执行编译,发现没有进dist目录下
{..."compilerOptions": {"target": "ES6","module": "ES6","outDir": "./dist",//是否对我们js文件进行编译,默认是false"allowJs": true}}
checkJs
是否检查js代码的语法是否符合语法规范,默认是false
{..."compilerOptions": {"target": "ES6","module": "ES6","outDir": "./dist","allowJs": true,"checkJs": false}}
removeComments
是否移除注释
noEmit
不生成编译后的文件
有些时候,就是我不想ts的编译功能,只想用ts去检查一下语法
其实使用几率不是那么大
onEmitOnError
也是不生成js代码,但是这个有一个前提条件,就是当有错误的时候,不生成编译后的文件
语法检查的
alwaysStrict
严格模式的语法
怎么开启严格模式
js文件为例:手动加上一个字符串
"use strict"let b = 20;let c = 'hello';
这就表示开启了我们的严格模式
在ts文件下进行编译的时候,是不会带严格模式,但凡,我们需要在ts里面使用严格模式就会用到alwaysStrict**alwaysStrict**:用来设置编译后的文件是否使用严格模式,默认是false
{..."compilerOptions": {"target": "ES6","module": "ES6",// "lib": ["ES6","DOM"],"outDir": "./dist",// "outFile": "./dist/app.js""alwaysStrict": true}}
就会默认在一个严格模式下了
noImplicitAny
Any我们都知道是ts中的一个类型,当我们整一个变量不指定类型,这个变量的默认类型就是any
function fun(a,b){return a+b}
any一旦设置实际上就关闭了我们ts对所有类型的检查,所以我们是不推荐使用any的,但是我们使用了any,ts中没有任何的报错,这时候帮我们检查是否有隐式的any的时候,我们就可以使用noImplicitAny
{..."compilerOptions": {"target": "ES6","module": "ES6",// "lib": ["ES6","DOM"],"outDir": "./dist",// "outFile": "./dist/app.js""noImplicitAny": true}}
上面隐式的any就会报错
**noImplicitAny**:不允许隐式的any
noImplicitThis
与**noImplicitAny**类似
不允许不明确类型的this
function fun2(){alert(this)}
你不确定this是什么;你用到的方法它没有,那这个时候,我们就希望ts编译器它可以把这个错误和隐患给我们检查出来
{..."compilerOptions": {"target": "ES6","module": "ES6",// "lib": ["ES6","DOM"],"outDir": "./dist",// "outFile": "./dist/app.js""noImplicitAny": true,"noImplicitThis": true}}
这时this就报错了
说白了我不明确这个this到底是什么
怎么解决这个问题
function fun2(this:any){alert(this)}
或是知道是一个window:
function fun2(this:Window){alert(this)}
不允许不明确类型的this
strictNullChecks
严格的检查空值
let box1 = document.getElementById('box1');box1.addEventListener('click',function(){alert('hello');})
这是js中很简单的点击事件,但是,我确定这个box1这个元素浏览器里有吗?
可能box1不存在,不存在的话,就是null,可能会报错。但是ts编译器没有给我检查出来这个问题,就是因为strictNullChecks没有设置为true提醒我
{..."compilerOptions": {"target": "ES6","module": "ES6",// "lib": ["ES6","DOM"],"outDir": "./dist",// "outFile": "./dist/app.js""noImplicitAny": true,"noImplicitThis": true,"strictNullChecks": true}}
就会给你提示:
box1对象可能为null
怎么解决这个问题?
可以做一个判断:
let box1 = document.getElementById('box1');if(box1 != null){box1.addEventListener('click',function(){alert('hello');})}
或者
let box1 = document.getElementById('box1');box1?.addEventListener('click',function(){alert('hello');})
strict
所有严格检查的总开关
这个如果为true,以上几个严格语法检查全部打开
也就是:
{..."compilerOptions": {"target": "ES6","module": "ES6",// "lib": ["ES6","DOM"],"outDir": "./dist",// "outFile": "./dist/app.js""strict": true,/*strict为true,以下的几个严格检查都可以省略不写"noImplicitAny": true,"noImplicitThis": true,"strictNullChecks": true*/}}
一般开发建议,改为true
其实配置还有很多,一边学一边用
