20分钟学会TypeScript

前言

TypeScript已经成为前端必备技能了,以下是TypeScript的优势

  1. 静态类型检查:TypeScript是JavaScript的超集,它引入了静态类型检查,可以在编译时发现类型错误,减少在运行时出现的错误。这可以提高代码的可靠性和维护性。
  2. 更好的开发工具支持:TypeScript提供了更好的开发工具支持,如代码自动补全、代码导航、重构和调试等功能。这些工具可以提高开发效率,并减少调试和排错的时间。
  3. 更好的代码组织和重用:TypeScript支持面向对象的编程风格,可以使用类、接口、模块等概念来组织和重用代码。这有助于提高代码的可读性、可维护性和可扩展性。
  4. 更好的团队协作:TypeScript的静态类型检查可以帮助团队成员更好地理解和使用代码,减少因为类型错误导致的沟通和协作问题。此外,TypeScript还支持定义类型声明文件,可以提供给其他团队成员使用,减少对代码的依赖和理解成本。
  5. 兼容性和迁移性:TypeScript兼容JavaScript的语法和库,可以无缝地集成到现有的JavaScript项目中。此外,TypeScript还提供了一些工具和指南,可以帮助开发者将现有的JavaScript代码逐步迁移到TypeScript。

开始使用TypeScript

在项目中安装TypeScript

1
npm i typescript -g

在TypeScript官网打开演练场
TypeScript官网

类型推断

1
2
3
4
// bad
let str = 'abc'
str = 10
// typescript会根据你给变量存放的初始值来进行变量类型限定,这在我们开发中很有意义,因为变量一旦分配了字符串值,那意味着后期可能会书写一些字符串相关功能,比如方法等相关的操作,如果过程中突然分配了一个数值,那意味着这些针对字符串的操作都是会出现错误的,为了避免这些情况,我们才需要使用TypeScript

类型注解

1
let str:string = 'abc' || let str:string  str = 'abc'

类型断言

1
2
3
4
5
6
7
8
9
10
11
// bad
let numArr = [1,2,3]
// find() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。
const result = numArr.find(item => 2)
result * 5

// 假如我们确定result的最终的结果是必然有值大于2的,那我们就可以通过类型断言的方式来设置
// good
let numArr = [1,2,3]
const result = numArr.find(item => 2) as number
result * 5

基础类型和联合类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let v1: string = 'abc'
let v2:number = 10
let v3:boolean = true
let nu:null = null
let un:undefined = undefined
// 大家可能比较好奇,null和undefined不常用,为什么还要有,那是因为TypeScript还支持一种类型:联合类型
let v4:string | null = null
// null默认是可以分配给其他任意类型的,当我们勾选strictNullChecks时,我们就不能随意将null分配给其他类型

// 我们除了可以限制一些类型以外,还可以做一些具体值的限定
// bad
let v5: 1 | 2 | 3 = 5
// good
let v5: 1 | 2 | 3 = 2

数组、元组、枚举

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
// 数组
// bad
let arr:number[] = [1,2,3,'a']
// good
let arr:number[] = [1,2,3]
// good
let arr1: Array<string> = ['a','b','c']

// 元组
let t1:[number,string,number] = [1,'a',2]
// bad
t1[0] = 'a'
// 其实在操作的时候,这个元组并不是说完全必须得是三个值,如果希望某个值可选得话,你也可以采用一个'?'的方式来写一个可选参数
// good
let t1:[number,string,number?] = [1,'a']

// 枚举
// 枚举需要使用一个新的关键字叫 enum[ɪˌnjuːm],一般枚举首字母大写
enum MyEnum {
A,
B,
C
}
// 这里我们可以使用两种方式来操作,第一种方式我们可以使用:'MyEnum.A',或者我们可以利用值的方式来访问枚举类型:'MyEnum[0]',枚举类型当我们声明好以后它是会自动做值的分配,默认是从0分配,a是0,b是1,c是2
console.log(MyEnum.A) //0
console.log(MyEnum[0]) //A

函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//void类型,void其实就是空的意思,void只能被分配undefined(严格模式),一般我们很少会给变量去赋值void,通常是一个函数,比如一个函数没有返回值的时候,默认返回undefined
function myfn(a:number,b:string):void {
console.log(a+b)
}
// 除了可以这样写以外,还有一些其他用法,比如可以把这些参数设置成可选的参数,这和我们使用的ES6是比较类似的,所有的可选参数应该在必选参数的后面
function myfn(a:number,b?:string):void {
if(b) {
console.log(a+b)
} else {
console.log(a)
}
}
// 注意'?'这种写法只能在TypeScript使用

// 除此之外,也可以将参数设置默认值,设置剩余参数
function myfn(a:number = 10,b:string,c?:boolean,...rest:number[]):void {
console.log(a+b)
}
// bad
myfn(5,6,7,1,2,3)
// good
myfn(5,'6',true,1,2,3)

接口

1
2
3
4
5
6
7
8
9
10
// 接口的关键字是'interface',通常用来去进行一个对象的定义
interface Obj {
name:string,
age:number
}
const obj:Obj = {
name:'a',
age:10
}
// 这种方式就避免在声明数据的时候出现一些偏差

类型别名

1
2
3
4
5
6
7
8
9
// 比如需要定义几个用户名变量,可能是联合类型
let a: string | number = 10
let b: string | number = 20
let c: string | number = 'abc'
//使用类型别名,类型别名关键字'type'
type MyUserName = string | number
let a: MyUserName = 10
let b: MyUserName = 20
let c: MyUserName = 'abc'

泛型

1
2
3
4
5
6
7
8
9
function myFn(a:number,b:number):number[] {
return [a,b]
}
// 假设这个函数是一个比较通用的函数,既可以处理数字值,又可以处理字符串值,布尔值等等,这种情况下,想用它来传其他类型数据,就不可以了,因为它规定的是number,那有没有可能写number | string呢?那样的话会出现交叉使用的情况,为了避免这个问题,就可以采用泛型的概念
function myFn<T>(a:T,b:T):T[] {
return [a,b]
}
myFn<number>(1,2)
myFn<string>('a','b') || myFn('a','b')