TS 的开始 持续更新中....

434 阅读9分钟

从了解TS开始

他是基于JavaScript之上的语言的编程语言,在TypeScript官网写道,TypeScript是JS的超集,他重点解决了JavaScript自有的类型系统不足,通过使用TypeScript提高代码可靠度。

TS自身存在的缺点,他在自身多了很多的概念性的东西,并且开发周期短、项目小会增加开发的成本

简单了解一下语言类型

强类型与弱类型语言(类型安全)

从安全的角度去看,编程语言被分为强类型语言与弱类型语言两种,从语言层面去看看二者的概念

  1. 强类型语言的概念:在语言的层面上,不允许发生隐式转换
  2. 弱类型语言的噶年:在弱类型语言当中,隐式转换常常发生

静态类型与动态类型(类型系统)

从类型系统上进行语言的区分

  1. 静态类型:一个变量被声明的时候,类型就已经确定了,在变量声明过后,是不允许被改变的
  2. 动态类型:正在代码执行的过程中,类型才能被确定,而且变量是可以随意进行修改的

JavaScript类型系统的特征

为什么JavaScript不能被设计成强类型/静态类型的语言,跟JavaScript早年被开发出来有关联

  1. 在早前没想到现在应用的广泛,早前应用的很简单
  2. JavaScript是一门脚本语言,脚本语言的特点是不需要进行编译的环节的,直接在运行环境当中进行运行

可以看出JavaScript它是一门动态类型/弱类型的语言,灵活

TS 的安装

  1. 通过 npm 的方式进行全局安装,当然你也可以在项目中安装 TS ,个人比较喜欢在全局安装一个,然后项目中如果他要是用的话在安装也是可以的
npm install typescript -g
  1. 查看当前安装的 TS 版本
tsc -v
  1. 编译 TS 文件,侦听单独的文件,如果有 TS 的配置文件,直接侦听 TS 配置文件
tsc xxx.ts  1. 编译TS 文件
tsc xxx.ts -w 2. 持续侦听,不需要每一次都执行
  1. 初始化一个 TS 配置文件
tsc --init
tsc -w 去侦听TS 的配置文件

TS 的初体验

  1. 使用 TS 的好处就是,类型的校验,在代码编译的过程中,将错误抛出来,看下面的代码
function sum(a:number,b:number) { 
    return a+b 
} 
console.log(sum('5',6))

函数的参数指定了类型,但是在调用的函数的时候,第一个参数传递的是 ‘字符串 5’ ,函数的第一个参数指定了 a 必须是一个值类型,而传递的是字符串,所以 TS 在编译的过程中,将错误抛出 Snipaste_2021-09-28_13-01-16.png

TS 的类型推断

基本类型的推断

在学习 TS 的过程中,当不明确需要设置的数据类型的时候, TS 会根据我们给变量赋的值,来推断我们定义的变量的类型

  1. 基本数据类型的推断,例如 number、string、boolean的类型推断
let b = 'a是string类型'  推断 变量 a 的类型为‘string’ ,以此类推
let a = true
let c = 0

当鼠标悬停到变量 b 的时候,系统会给我们进行推断,推断b的类型是 ‘string’

  1. 在操作函数的时候,函数的参数没有设置类型,系统会推断,参数类型是 any 类型,也就是任意类型都可以传递给函数,在操作对象的时候,也是如此,因为没有明确的值,系统无法推断具体的类型,所以在 TS 中操作函数\对象的时候,需要指定类型
function sum(a: number,b :number) : string {  
    1. 在设置类型的时候,还可以指定函数返回值的数据类型 
    return '计算结果是:' + a + b 
}
sum(5,6)

Array数组的推断

  1. 普通的数据类型推断,数组的推断也是有所不同的,需要注意的是,当定义一个有值的数组时候,鼠标悬停到数组变量上,会显示【 let arr : (string | number)[ ] 】,他代表的是,这个变量是数组类型,并且里面只能去添加字符串与数值类型的‘值’。像数组中添加布尔类型是不可以的

  1. 通过设置类型,允许向数组中添加哪一些类型的操作
let arr: (string | number | boolean)[] = [] 
arr.push('100')

对象的类型推断

  1. 对于对象内部的数组,如果数组里存放的是对象类型结构的值,在类型设置&类型推断的时候,都是一个对象类型,并且内部的值也是具体的类型

  2. 在修改对象内部某一个属性的时候,也会根据类型去推断,显示对象里面某一个属性值的类型

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 }
  1. 可选参数类型的设置:在某些情况下,某一些值特定情况下是可以不用传递的,也就是可传递可不传递的一种状态,在 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)
  1. 普通的设置函数参数的方式 ‘a: number’
  2. 如果有一个参数是可以传递或者是不传递 ‘redio?:number’ 也就是在参数的后面拼接‘?’代表这个参数可以传或者是不传递
  3. 可选参数设置默认值 ‘redio: number = 0.6’

函数返回值

TS 中对于函数的返回值,系统会根据函数参数的类型,进行推断,推断函数的返回值的类型

  1. 普通函数的返回值
1. 第一种情况,函数在有返回值的情况下,设置函数返回值的类型 
function fun(a:number,b:number): string { 
    /* 指定函数的返回值 */ 
    return `${a+b}` 
} 
console.log(fun(5,6)); 
2. 第二种情况,一些特殊特殊的时候函数是没有返回值的,这时候函数的返回值是一个‘void’类型 
function fun():void { 
    console.log('函数没有返回值') 
}
  1. 箭头函数的返回值
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. 数组与元素的类型推断的差别
1. 元组 他的类型推断是一个 readonly [] 是一个只读的
let arr: readonly [] // 元组 
let tuple: [number, string] // 元组

2. 数组
let arr: number[] // 数组