从了解TS开始
他是基于JavaScript之上的语言的编程语言,在TypeScript官网写道,TypeScript是JS的超集,他重点解决了JavaScript自有的类型系统不足,通过使用TypeScript提高代码可靠度。
TS自身存在的缺点,他在自身多了很多的概念性的东西,并且开发周期短、项目小会增加开发的成本
简单了解一下语言类型
强类型与弱类型语言(类型安全)
从安全的角度去看,编程语言被分为强类型语言与弱类型语言两种,从语言层面去看看二者的概念
- 强类型语言的概念:在语言的层面上,不允许发生隐式转换
- 弱类型语言的噶年:在弱类型语言当中,隐式转换常常发生
静态类型与动态类型(类型系统)
从类型系统上进行语言的区分
- 静态类型:一个变量被声明的时候,类型就已经确定了,在变量声明过后,是不允许被改变的
- 动态类型:正在代码执行的过程中,类型才能被确定,而且变量是可以随意进行修改的
JavaScript类型系统的特征
为什么JavaScript不能被设计成强类型/静态类型的语言,跟JavaScript早年被开发出来有关联
- 在早前没想到现在应用的广泛,早前应用的很简单
- JavaScript是一门脚本语言,脚本语言的特点是不需要进行编译的环节的,直接在运行环境当中进行运行
可以看出JavaScript它是一门动态类型/弱类型的语言,灵活
TS 的安装
- 通过 npm 的方式进行全局安装,当然你也可以在项目中安装 TS ,个人比较喜欢在全局安装一个,然后项目中如果他要是用的话在安装也是可以的
npm install typescript -g
- 查看当前安装的 TS 版本
tsc -v
- 编译 TS 文件,侦听单独的文件,如果有 TS 的配置文件,直接侦听 TS 配置文件
tsc xxx.ts 1. 编译TS 文件
tsc xxx.ts -w 2. 持续侦听,不需要每一次都执行
- 初始化一个 TS 配置文件
tsc --init
tsc -w 去侦听TS 的配置文件
TS 的初体验
- 使用 TS 的好处就是,类型的校验,在代码编译的过程中,将错误抛出来,看下面的代码
function sum(a:number,b:number) {
return a+b
}
console.log(sum('5',6))
函数的参数指定了类型,但是在调用的函数的时候,第一个参数传递的是 ‘字符串 5’ ,函数的第一个参数指定了 a 必须是一个值类型,而传递的是字符串,所以 TS 在编译的过程中,将错误抛出
TS 的类型推断
基本类型的推断
在学习 TS 的过程中,当不明确需要设置的数据类型的时候, TS 会根据我们给变量赋的值,来推断我们定义的变量的类型
- 基本数据类型的推断,例如 number、string、boolean的类型推断
let b = 'a是string类型' 推断 变量 a 的类型为‘string’ ,以此类推
let a = true
let c = 0
当鼠标悬停到变量 b 的时候,系统会给我们进行推断,推断b的类型是 ‘string’
- 在操作函数的时候,函数的参数没有设置类型,系统会推断,参数类型是 any 类型,也就是任意类型都可以传递给函数,在操作对象的时候,也是如此,因为没有明确的值,系统无法推断具体的类型,所以在 TS 中操作函数\对象的时候,需要指定类型
function sum(a: number,b :number) : string {
1. 在设置类型的时候,还可以指定函数返回值的数据类型
return '计算结果是:' + a + b
}
sum(5,6)
Array数组的推断
- 普通的数据类型推断,数组的推断也是有所不同的,需要注意的是,当定义一个有值的数组时候,鼠标悬停到数组变量上,会显示【 let arr : (string | number)[ ] 】,他代表的是,这个变量是数组类型,并且里面只能去添加字符串与数值类型的‘值’。像数组中添加布尔类型是不可以的
- 通过设置类型,允许向数组中添加哪一些类型的操作
let arr: (string | number | boolean)[] = []
arr.push('100')
对象的类型推断
-
对于对象内部的数组,如果数组里存放的是对象类型结构的值,在类型设置&类型推断的时候,都是一个对象类型,并且内部的值也是具体的类型
-
在修改对象内部某一个属性的时候,也会根据类型去推断,显示对象里面某一个属性值的类型
TS 明确类型的设置
需要注意的是,当变量类型明确以后,传递其他类型的值是不对的,必须要传递相应的数据类型的值,才可以
基本数据类型
let str: string = 'css'
let num: number = 100
let bool: boolean = true
let arr: (string | number)[] = []
对象
let obj: { name: string,age: number }
obj = { name: "小明",age: 18 }
- 可选参数类型的设置:在某些情况下,某一些值特定情况下是可以不用传递的,也就是可传递可不传递的一种状态,在 TS 中可以通过 【?】 标识符,设置可选传递值
let obj: {name: string , lesson: {}[] , url?: string}
通过类型设置的时候,在后面通过使用 ‘?’来设置这个参数是可选的,在创建对象的时候,可以不设置这个属性
let obj: {name: string,age:number,url? : string,lesson: {}[]}
obj = {
name: '小明',
age: 18,
lesson: [ { name: '小红', age: 18 } ]
}
联合类型声明
联合类型的声明,变量可以定义多个类型的声明,传递与其对应的类型值,是不会发生错误的,联合类型的声明通过管道符进行链接【|】
let a: number | string | true let
arr: (string | number | true)[]
any、unknow、void、never
任意类型any
TS 中有一个类型叫 any ,any类型是任意类型的定义,通过将变量的类型定义成 any,代表着这个变量可以被设置成任意类型的数据,在 TS 中不推荐将变量或者是参数类型定义成 any ,如果定义成 any 那么 TS 与 JavaScript 也没什么区别了,所以不推荐,但特殊的情况下还是需要使用 any 的
let arr: any[] = []
无明确类型的unKnown类型
在 TS 里面,unknown类型他没有明确的类型,不知道他的类型是什么,如果使用了类型为unknown的变量,去赋值给另一个变量,这时候就需要使用类型断言,告诉其他变量,我的这个变量是什么类型的
let a: unknown = 'unknown'
let str:string = a as string /* as告诉前面的变量,我的这个数据类型是什么 */
在某些时候,想要将一个类型转换成另一个数据类型,来赋值给另一个变量,这时候可以使用类型断言,可以去借助 unknown 类型,作为中间类型,来实现两个类型之间的赋值操作
let str:string = '99'
let num: number = str as unknown as number
void类型
void类型,它可以是空‘null’,也可以是‘undefined’,此类型只能是这啷个值,不可以被赋值成其他的类型,void 类型一般多用于函数的返回值类型
function sum(): string | void {
/* 返回值是undefined,函数不明确的返回值 */
return 'typescript' }
console.log(sum())
never类型
never类型他没有任何值,使用的场景函数身上,当函数执行错误,或者是并没有执行结果会使用never类型,或者是函数执行不到最后
function sum(): never {
throw new Error('类型错误')
}
console.log(sum())
null & undefined类型
在声明【null,undefined】类型的数据的时候,他们的值必须分别是【null,undefined】,但是需要注意的,null于undefined可以做为其他类型数据的值,他们的使用情况多用于函数的返回值,但推荐使用 void 类型作为函数的返回值操作
let n: null = null
let un: undefined = undefined
/------------------------------------/
let str: string = 'typescript'
str = undefined
console.log(str)
function sum(): null | undefined | string {
return 'typescript'
}
console.lgo(sum())
函数在 TS 中使用
函数类型可以指定类型后,在进行赋值,也可以使用类型断言,将函数赋值给另一个变量
let sum =()=> {} // 普通声明
let sum:Function;
sum =()=> {}
let a:string = fun as unknown as string // 使用类型断言,将函数类型转换赋值给字符串类型‘a’
函数参数
function sum( a:number, b:number, redio?: number = 6) {
return a + b
}
sum(2,5)
- 普通的设置函数参数的方式 ‘a: number’
- 如果有一个参数是可以传递或者是不传递 ‘redio?:number’ 也就是在参数的后面拼接‘?’代表这个参数可以传或者是不传递
- 可选参数设置默认值 ‘redio: number = 0.6’
函数返回值
TS 中对于函数的返回值,系统会根据函数参数的类型,进行推断,推断函数的返回值的类型
- 普通函数的返回值
1. 第一种情况,函数在有返回值的情况下,设置函数返回值的类型
function fun(a:number,b:number): string {
/* 指定函数的返回值 */
return `${a+b}`
}
console.log(fun(5,6));
2. 第二种情况,一些特殊特殊的时候函数是没有返回值的,这时候函数的返回值是一个‘void’类型
function fun():void {
console.log('函数没有返回值')
}
- 箭头函数的返回值
let fun =():vido => console.log('箭头函数的返回值,并没有')
type简单了解(接口中详细了解)
使用 type 关键字,对一些公共的类型定义,进行抽取,他也是一种约束,通过type的定义,他会约束函数,必须传递这些参数,并且类型要与之相同
在图中可以看到,两个函数的参数类型定义是相同的,这时候可以去使用type对参数进行统一的定义
函数的结构定义
1. 对函数的简单限制,并不能限制内部的内容,这样只能对函数自身类型的限制,不限制参数以及返回值
let fun: Function fun =()=> {} fun被赋值为函数,其他类型是不可以的
2. 更严格的类型定义,包含返回值以及参数的类型
let fun:(a:number,b:number) => number
‘fun’函数的具体实现,并且注意的是, 具体实现可以不与定义的函数参数类型名字一样,也是可以的
fun =(x,y)=> { return x + y }
使用 type 对函数进行描述
使用type对函数进行描述, 也就是定义了一个函数类型 , 然后通过这个函数类型去约束另一个函数,被约束的变量就必须是一个函数
type userType = {name: string ,age: number}
type userAddFun = (user:userType) => string
let addUser: userAddFun = (user:userType):string => {
return `${user.name} ${user.age}`
}
console.log(addUser({name: 'type',age: 25}));
元组tuple
元素类型与数组很相似,但是元素比起数组,他们之间的不同点,元组里面的数据,不限制类型元素,但是每一个元素必须要和他的类型进行一一的对应,位置上也是不可以发生变化的
1. 元组的声明
let tuple: [number,string] = [1,'11']
2. 对比数组的定义
let arr: (number | string | boolear)[] = []
注意! 如果你要去修改元组里面的值,必须修改成对应类型的数据,从上面可以看到,他们必须要与类型定义的位置一致
tuple[0] = 'str' // 报错
tuple[0] = 99 // 正常打印
- 数组与元素的类型推断的差别
1. 元组 他的类型推断是一个 readonly [] 是一个只读的
let arr: readonly [] // 元组
let tuple: [number, string] // 元组
2. 数组
let arr: number[] // 数组