前言
JS缺点
- 不适合复杂的面向对象开发的情况
- 维护困难
- 动态类型有安全隐患
- 太少报错,导致后面会出现更大问题
TS
以JavaScript为基础构建的语言;一个JavaScript的超集;微软写的,解决js的问题,比如静态类型;任何支持JavaScript的平台中执行;扩展了JavaScript;TS不能被js解析器直接执行,需要ts文件进行编译转化为js文件,浏览器才可以执行。
一. 基本类型
注意定义为什么类型,后期赋值的时候,只能是这个类型的数据
- 布尔
- 数字
- 字符串
- undefined和null
可以是任何类型的子类型 - 数组
let list1: number[] = [1,2,3] 或者 let list2: Array<number> = [1,2,3]
定义后里面的数据类型必须和定义数组时候的类型一致 - 元组
要保证数据类型和个数一致1
2
3
4
5let t1: [string, number]
t1 = ['hello', 10] // OK
t1 = [10, 'hello'] // Error
console.log(t1[0].substring(1)) // OKconsole.log(t1[1].substring(1)) // Error, 'number' 不存在 'substring' 方法 - 枚举
枚举中的元素可以是中文的数据值,但是不推荐1
2
3
4
5
6
7enum Color {
Red,
Green,
Blue
}
// 枚举数值默认从0开始依次递增// 根据特定的名称得到对应的枚举数值let myColor: Color = Color.Green // 0console.log(myColor, Color.Red, Color.Blue) - any
我们不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。 那么我们可以使用 any 类型来标记这些变量
- void
声明一个 void 类型的变量没有什么大用,因为你只能为它赋予 undefined 和 null
- object
非原始类型 - 联合类型
表示取值可以为多种类型中的一种1
2function toString2(x: number | string) : string {
return x.toString()} - 类型断言
通过类型断言这种方式可以告诉编译器,“相信我,我知道自己在干什么”。 类型断言好比其它语言里的类型转换,但是不进行特殊的数据检查和解构。 它没有运行时的影响,只是在编译阶段起作用。 TypeScript 会假设你,程序员,已经进行了必须的检查。类型断言有两种形式。 其一是“尖括号”语法, 另一个为 as 语法
1 |
|
- 类型推断
TS会在没有明确的指定类型的时候推测出一个类型
有下面2种情况: 1. 定义变量时赋值了, 推断为对应的类型. 2. 定义变量时没有赋值, 推断为any类型1
2
3
4
5/* 定义变量时赋值了, 推断为对应的类型 */let b9 = 123 // number// b9 = 'abc' // error
/* 定义变量时没有赋值, 推断为any类型 */let b10 // any类型
b10 = 123
b10 = 'abc'二.接口
TypeScript 的核心原则之一是对值所具有的结构进行类型检查。我们使用接口(Interfaces)来定义对象的类型。接口是对象的状态(属性)和行为(方法)的抽象(描述)
1 | // 定义人的接口interface IPerson { |
- 可选属性
sex?: string
可选属性的好处之一是可以对可能存在的属性进行预定义,好处之二是可以捕获引用了不存在的属性时的错误。
- 只读属性
readonly id: number
构造器中,可以对只读的属性成员进行修改
构造器函数中的参数,一旦使用readonly进行修饰后,那么该参数叫参数属性,会自动有一个属性成员(public,private,protected同理)
一旦赋值后再也不能被改变了。
readonly VS const
作为变量使用的话用const
。作为属性使用readonly
- 函数类型
接口能够描述 JavaScript 中对象拥有的各种各样的外形。 除了描述带有属性的普通对象外,接口也可以描述函数类型。为了使用接口表示函数类型,我们需要给接口定义一个调用签名。它就像是一个只有参数列表和返回值类型的函数定义。参数列表里的每个参数都需要名字和类型。
1 | /* |
- 一个类可以实现多个接口,一个接口也可以继承多个接口
三.类
与面向对象的语言一样
- 继承
- 多态
父类型引用指向了子类型的对象,不同类型的对象针对相同的方法,产生了不同的行为 - 不能通过实例对象直接调用静态属性或方法,可以通过类名.的方式使用
- 构造函数不能通过static进行修饰
- 抽象类,抽象方法abstract
不能实例化抽象类的对象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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
class Animal {
name: string
constructor (name: string) {
this.name = name
}
run (distance: number=0) {
console.log(`${this.name} run ${distance}m`)
}
}
class Snake extends Animal {
constructor (name: string) {
// 调用父类型构造方法
super(name)
}
// 重写父类型的方法
run (distance: number=5) {
console.log('sliding...')
super.run(distance)
}}
class Horse extends Animal {
constructor (name: string) {
// 调用父类型构造方法
super(name)
}
// 重写父类型的方法
run (distance: number=50) {
console.log('dashing...')
// 调用父类型的一般方法
super.run(distance)
}
xxx () {
console.log('xxx()')
}}
const snake = new Snake('sn')
snake.run()
const horse = new Horse('ho')
horse.run()
// 父类型引用指向子类型的实例 ==> 多态const tom: Animal = new Horse('ho22')
tom.run()
/* 如果子类型没有扩展的方法, 可以让子类型引用指向父类型的实例 */const tom3: Snake = new Animal('tom3')
tom3.run()/* 如果子类型有扩展的方法, 不能让子类型引用指向父类型的实例 */// const tom2: Horse = new Animal('tom2')// tom2.run()四.函数
与面向对象的语言一致 - 可选参数和默认参数
JavaScript 里,每个参数都是可选的,可传可不传。 没传参的时候,它的值就是 undefined。 在TypeScript 里我们可以在参数名旁使用 ? 实现可选参数的功能。
在 TypeScript 里,我们也可以为参数提供一个默认值当用户没有传递这个参数或传递的值是 undefined 时。 它们叫做有默认初始化值的参数。
- 剩余参数
剩余参数会被当做个数不限的可选参数。 可以一个都没有,同样也可以有任意个。 编译器创建参数数组,名字是你在省略号( …)后面给定的名字,你可以在函数体内使用这个数组。
1 | function info(x: string, ...args: string[]) { |
指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定具体类型的一种特性。
1 | //需求:定义一个函数,传入2个参数,第一个参数是数据,第二个参数是数量 |
- 泛型接口
在定义接口时, 为接口中的属性或方法定义泛型类型
在使用接口时, 再指定具体的泛型类型
1 | interface IbaseCRUD <T> { |
- 泛型类
在定义类时, 为类中的属性或方法定义泛型类型 在创建类的实例时, 再指定特定的泛型类型1
2
3
4
5
6
7interface Lengthwise {
length: number;}
// 指定泛型约束function fn2 <T extends Lengthwise>(x: T): void {
console.log(x.length)}
fn2('abc')// fn2(123) // error number没有length属性六.其他
- 引入外部文件
当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能。
声明语句: 如果需要ts对新的语法进行检查, 需要要加载了对应的类型说明代码
declare var jQuery: (selector: string) => any;
声明文件: 把声明语句放到一个单独的文件(jQuery.d.ts)中, ts会自动解析到项目中所有声明文件
下载声明文件: npm install @types/jquery –save-dev
1.根文件集成终端输入npm install jquery 2.方法太多了,如果每个方法都写一个jquery.d.ts声明文件,过于繁琐。使用npm install @types/jquery –save-dev下载声明文件
- 内置对象
JavaScript 中有很多内置对象,它们可以直接在 TypeScript 中直接使用
1.ECMAScript的内置对象
1 | Boolean |
2.BOM和DOM的内置对象
1 | Window |
ts在vscode自动编译
- 新建文件,在集成终端打开它,输入tsc –init,自动生成tsconfig.json文件
- 更改tsconfig.json的配置,outDir//输出目录。strict//严格模式:false
- 启动监视任务,终端–》任务运行–》显示所有任务
类型注解 :是一种轻量级的为函数或者变量添加的约束
接口
是一种能力,一种约束而已
1 | (()=>{ |
函数
1 | (()=>{ |
webpack打包ts
- 建public/index.html和src/main.ts以及build/webpack.config.js
build/webpack.config.js
1 | const {CleanWebpackPlugin} = require('clean-webpack-plugin')const HtmlWebpackPlugin = require('html-webpack-plugin')const path = require('path') |
- 终端打开根文件夹,输入npm init -y,会自动生成package.json。输入tsc –init,会自动生成tsconfig.json
- 下载依赖
1 | yarn add -D typescript |
终端依次输入npm install -D typescript npm install -D webpack@4.41.5webpack-cli@3.3.10 webpack-dev-server@3.10.2 npm install -D html-webpack-plugin clean-webpack-plugin ts-loader cross-env
- 配置打包目录package.json
1 | scripts:{ |
- 运行
npm run dev
- 配置
`npm run build