第一章 ts特点
与js的区别
- 以js为基础构建的语言
- 一个js的超集
- 可以在任何支持js的平台中运行
- ts扩展了js,并添加了类型
- ts不能被js解析器直接执行
- 在编译过程中,ts还是编译成js
增加特性
- 类型
- 支持ES新特性
- 添加ES不具备的新特性
- 丰富的配置选项
第二章 ts开发环境搭建
下载node.js
下载链接:Node.js (nodejs.org)
1 | // 检查node是否下载成功 |
命令安装ts
- 全局安装
1 | npm i -g typescript |
创建并打开ts文件
- 命令行创建空文件
1 | touch helloTs.ts |
- 使用vscode打开文件
运行ts文件
在ts文件的目录下打开控制台,输入
1
node helloTs.ts
编译为js文件
在ts文件目录下打开控制台,输入
1
tsc helloTs.js
第三章 基本类型
可以让我们的变量赋予类型
let valuable: [type]
型
1 | // 将变量a赋予类型number |
- 如果变量的声明和赋值时同时进行的。ts可以自动对变量进行类型检测
1 | // 这个时候已经赋予类型boolean了 |
可以对我们的函数赋予类型
给参数赋予类型
1
2
3
4
5
6
7
8function sum (a: number, b: number) {
reutrn (a + b)
}
console.log(sum(123, 456))
// 报错
console.log(sum(123, "456"))当然,参数个数也是严格把控了
1
2// 报错
console.log(sum(123, 456, 789))函数表达式的赋予类型
- 可以同时标注:
- 参数个数与基本类型
- 返回值类型
1
let fn: (a: number, b: string) => boolean
- 可以同时标注:
基本类型
- 一览表
类型 | 例子 | 描述 |
---|---|---|
number | 123 | |
string | “hello” | |
boolean | true | |
字面量 | 本身 | 限制变量的值就是该字面量的值 |
any | * | 任意类型 |
unknown | * | 类型安全的any |
void | 空 | 没有值(undefined) |
never | 没有值 | 不能是任何值 |
object | {a: 1} | |
array | [1, 2, 3] | 任意的js数组 |
tuple | [4, 5] | 固定长度的数组 |
enum | enum(A, B) | 枚举 |
字面量的定义使用
1 | // 将 10 作为给自己使用不能改变 |
- 当然,我们可以当作枚举这么使用
1 | let a: "male" | "female" |
- 一般用于连接多个类型
1 | let a: string | number |
any的使用
- 使用之后跟js很相似,不进行类型检错
unknown的使用
使用之后表示未知类型的值
与any的区别:any可以随意赋值给其他的类型,而unknown不行
但是any和unknown被赋值的时候是极其相似的
unknown类型就是一个类型安全的any
1
2
3
4let a: string = "str"
let b: unknown = "123"
b = a // true
a = b // false
类型断言
语法
- a = b as [type]
- a =
b
1
2
3a = b as string
a = <string>b用处:用于判断赋值的类型
never的使用
一般用于设置函数的返回值【没有值】
表示永远不会返回结果
和void的区别:void返回是空,never是不返回,只throw错误
1
2
3
4
5
6
7
8
9
10
11
12
13
14function fn () : never {
throw new Error("err")
}
### object的使用
- 最基本的定义就是设置变量是否为对象
```typescript
let obj: object;
obj = {} // ok
obj = 123 // error当然,也可以这么表示,直接用object的符号{}表示【很像字面量法但却有点区别】
1
2let obj: {}
obj = {name: 123} // ok此外,如果你想对object内部的对象的
属性
和属性格式
做一点要求,你也可以这么做【?表示可选】1
2
3
4
5let obj: {name: string, AGE?: number}
obj = {age: 123} //error
obj = {name: "smith", age: 123} // ok
obj = {name: 123} // error你也可以对所有的属性的格式进行统一的要求
1
2
3
4
5let c = {name: string, [propName: string]: string} // ok
let num: {name: string, [propName: string]: number}// error 因为会和name发生冲突
c = {name: "123", age: 123}// ok
array类型的声明
- [type][]方法
- Array
方法
1 | let e: string[] //声明字符串数组 |
tuple类型
定义:固定长度的数组
声明方法:每一个都要声明,不然无法凸显长度和每一个元素的类型
1
2
3let h: [string, number]
h = ["123", 123]// ok
h = [123]// error
enum类型
- 用于定义枚举变量,可以用于定类型时设置字面量
1 | enum Gender { |
我们甚至可以对类型起别名
1 | type myT = 1 | 2 | string |
第四章 编译选项
热编译
- 我们应该要有一边修改一边编译的效果,下面是只更新一次的
1 | tsc hello.ts |
- 我们需要在控制台将上述的命令行修改
1 | tsc hello.ts -w |
- 有点类似于nodemon
全部执行
- 不输入具体文件名即可
- 接下来只需要执行
tsc
即可
1 | tsc |
编译配置环境
但是我们必须得有一个配置文件,不然无法执行
需要一个
tsConfig.json
,是ts编译器的配置文件,ts编译器可以根据它的信息来对代码进行编译include:用来指定哪些ts文件需要被编译
**:表示任意目录
*:表示任意文件
1
2
3{
"include": ["./src/**/*"]
}exclude:用来指定哪些文件不需要被编译
默认值:[“node_modules”, “bower_components”, “jspm_packages”]
1
2
3{
"exclude": ["./src/hello/*"]
}
complierOptions:用来指定编译器选项
- target:指定编译js的版本 ESNext为最新版本
- module:指定使用的模块化的规范
- lib:用来指定项目中要使用的库,一般在项目中不使用它
- outdir:指定编译之后生成的文件放置的目录
- outFile:将代码合成一个文件,并且指定合称文件
- allowJs:是否对文件进行js编译,默认为false
- checkJs:是否将js依照ts语法规范检查,默认为false
- removeComments:是否移除注释
- noEmit:是否生成编译后的文件
- noEmitOnError:报错之后是否生成编译后的文件
- alwaysStrict:是否编译后的文件是否开启严格模式
- noImplicitAny:不允许不明确【类型】的this,解决方法:this作为变量,类型为window
- strictNullChecks:严格检查空值
- strict:所有的严格模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18{
"compilerOprions": {
"target": "ES6",
"module": "commonjs",
"lib": [],
"outdir": './dist',
"outFile": './dist/App.js',
"allowJs": false,
"checkJs": false,
"removeComments": true,
"noEmit": false,
"noEmitOnError": true,
"alwaysStrict": false,
"noImplicitAny": false,
"strictNullChecks": false,
"strict": false
}
}
第五章 webpack打包ts代码
搭建初始开发环境(js)
对空文件夹进行依赖注入
1
npm init -y
安装webpack和ts的开发环境依赖
1
npm i -D webpack webpack-cli typescript ts-loader
在项目根目录下创建webpack.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24const path = require('path')
module.exports = {
// 指定入口文件
entry: './src/index.js',
// 指定打包文件所在的目录
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bandle.js'
},
// webpack打包时要使用的模块
module: {
rules: [
{
// 制定规则生效的文件
test: /\.ts$/,
// 使用的东西
use: 'ts-loader',
// 要排除的文件
exclude: /node-modules/
}
]
}
}
注意不要忘记了ts的配置
在package.json的
scripts
中添加:"build": "webpack"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19{
"name": "my-webpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"ts-loader": "^9.2.6",
"typescript": "^4.4.4",
"webpack": "^5.64.0",
"webpack-cli": "^4.9.1"
}
}
搭建自动生成HTML文件环境(HTML)
根目录下输入
1
cnpm i -D html-webpack-plugin
在
webpack.config.js
中引入html插件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29const path = require('path')
const HTMLWebpackPlugin = require('html-webpack-plugin')
module.exports = {
// 指定入口文件
entry: './src/index.js',
// 指定打包文件所在的目录
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bandle.js'
},
// webpack打包时要使用的模块
module: {
rules: [
{
// 制定规则生效的文件
test: /\.ts$/,
// 使用的东西
use: 'ts-loader',
// 要排除的文件
exclude: /node-modules/
}
]
},
plugins: [
// 配置Webpack插件
new HTMLWebpackPlugin(),
]
}执行命令行,可以生成HTML文件
1
npm run build
当然,我们可以对插件进行传参
1
2
3
4
5
6
7plugins: [
new HTMLWebpackPlugin(options: {
title: "myTitle",
// 选择模板
template: './src/index.js'
})
]
编辑脚手架环境
编辑开发运行环境
1
cnpm i -D webpack-dev-server
在package.json中编辑【添加】命令
1
2
3"scripts": {
"start": "webpack serve --open chrome.exe"
}在webpack.config.js中添加
1
mode: 'development'
运行程序
1
npm start
安装用于专门删除dist文件夹的环境,避免重复打包有旧文件
1
cnpm i -D clean-webpack-plugin
在plugin中添加
1
2
3
4
5plugins: [
// 配置Webpack插件
new HTMLWebpackPlugin(),
new CleanWebpackPlugin(["dist"])
]
设置引用模块
1
2
3resolve: {
extensions: ['.ts', '.js']
}
考虑兼容性
安装babel解决兼容性问题
babel的作用就是将高版本的js转换为低版本的js
1
cnpm i -D @babel/core @babel/preset-env babel-loader core-js
对webpack.config.js中的module进行修改
我们可以在target中写出我们需要兼容的软件
corejs的作用,一些浏览器根本没有高版本的语法糖,比如ie没有Promise,那么此时就算转换低版本不会出现Promise,这个时候corejs可以将Promise的功能做一个低版本方式的替换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25use: [
{
// 指定加载器
loader: "babel-loader",
// 设置babel
options: {
presets: [
[
// 指定环境的插件
"@babel/preset-env",
// 配置信息
{
targets: {
"chrome": "88",
},
"corejs": "3",
// 使用corejs的方式"usage"
"useBuiltIns": "usage"
}
]
]
}
},
'ts-loader'
],注意,webpack有一个立即执行函数,他是箭头函数,但是箭头函数并不兼容ie,而且这个立即执行函数也没有经过babel处理过,我们要想让该立即执行函数也可以被处理,我们需要在output中加上:
1
2
3environment: {
arrowFunction: false
}
函数的泛型
- 当我们不知道我们需要什么类型的时候,就可以使用泛型,就有点类似于C++的函数模板
1 | function fn<T>(a: T): T { |
- 类型不确定,只有函数执行的时候我们才确定,还有最好的话最好执行函数的时候手动输入泛型
1 | fn<String>(a: "hello") |
- 当然,泛型也不一定只有一个
1 | function fn2 <T, K> (a: T, b: K): T{ |
我们有的时候需要限制泛型的范围,我们需要用到用到extends字段
extends是子集,泛型T必须要包含Inter的特性
1 | interface Inter { |