TypeScript

164 阅读7分钟

1. 为什么要有typescript

内容:
 背景:JS 的类型系统存在“先天缺陷”弱类型,JS 代码中绝大部分错误都是类型错误(Uncaught TypeError)
 开发的时候,定义的变量本应该就有类型
这些经常出现的错误,导致了在使用 JS 进行项目开发时,增加了找 Bug、改 Bug 的时间,严重影响开发效率
为什么会这样? var num = 18 num.toLowerCase()
从编程语言的动静来区分,TypeScript 属于静态类型的编程语言,JavaScript 属于动态类型的编程语言

-   静态类型:编译期做类型检查
-   动态类型:执行期做类型检查
代码编译和代码执行的顺序:1 编译 2 执行
对于 JS 来说:需要等到代码真正去执行的时候才能发现错误(晚)
对于 TS 来说:在代码编译的时候(代码执行前)就可以发现错误(早)
并且,配合 VSCode 等开发工具,TS 可以提前到在编写代码的同时就发现代码中的错误,减少找 Bug、改 Bug 时间

对比:
使用 JS:
1.  在 VSCode 里面写代码
2.  在浏览器中运行代码 --> 运行时,才会发现错误【晚】

使用 TS:
1.  在 VSCode 里面写代码 --> 写代码的同时,就会发现错误【早】
2.  在浏览器中运行代码

2.编译 TS

image.png

3.安装编译 TS 的工具包

image.png

4.运行ts代码

image.png

image.png

5.什么是类型注解?

定义:给变量声明一个类型,在代码运行过程中变量的值不能发生变化

TypeScript 类型系统的主要优势:可以显示标记出代码中的意外行为,从而降低了发生错误的可能性  

image.png

image.png

6.TypeScript类型注解分类

image.png

7.TS数组的声明

image.png

8.联合类型

目标:能够通过联合类型将多个类型组合成一个类型

image.png

9.类型别名

目标:能够使用类型别名给类型起名字
 内容:
      类型别名(自定义类型):为任意类型起别名
      使用场景:当同一类型(复杂)被多次使用时,可以通过类型别名,简化该类型的使用
type CustomArray = (number | string | boolean)[]
let arr1: CustomArray = [1, 'a', 3, 'b', true]
let arr2: CustomArray = ['x', 'y', 6, 7, false]    

image.png

10.函数类型

目标:能够给函数指定类型
内容:
      函数的类型实际上指的是:`函数参数``返回值`的类型
      注意:必须给参数指定类型
      
//复杂类型注解:数组,函数,对象
//函数的类型注解:学习的是函数的参数 与 返回值 的类型注解
//在TS中:声明一个函数,参数必须给类型注解
//声明两个数值加法函数

 //声明式
    function add(n1 : number,n2 : number) : number {
     return n1 + n2
  }
    console.log(add(1,2));

 //表达式
   const sub = (n1 : number,n2 : number) : number =>{
      return n1 - n2
    }
      console.log(sub(10,2));   
      

image.png

11.void 类型

image.png

12.类型别名指定参数、返回值的类型

 解释:当函数作为表达式时,可以通过类似箭头函数形式的语法来为函数添加类型
 注意:这种形式只适用于函数表达式
 

image.png

13.可选参数

使用函数实现某个功能时,参数可以传也可以不传。这种情况下,在给函数参数指定类型时,就用到可选参数了
比如,数组的 slice 方法,可以 slice() 也可以 slice(1) 还可以 slice(1, 3)

image.png

image.png

14.对象属性的类型注解

 // 对象中如果有多个类型,可以换行写:
 // 通过换行来分隔多个属性类型,可以去掉 `;`
 // let obj: {
 //     name: string
 //     age:number
 //   } = {
 //     name: 'jack',
 //     age:18
 //   }
 
  练习:
      指定学生的类型
      姓名
      性别
      成绩
      身高
 
 let stu : {
             name : string
            gender :string
            score:number
            height:number
 } = {
       name : '小明',
       gender :'男',
       score:100,
       height:180
 }
   console.log(stu);
   

image.png

15.对象方法的类型注解

image.png

16.对象创建类型别名

 // 创建两个对象:
// 学生对象

// 指定对象的类型
// 姓名
// 性别
// 成绩
// 身高

// 学习
// 打游戏
// 创建类型别名
  type Person = {
     name: string
     gender:string
     score:number
     height:number
     study(): void
     play:(name:string)=>string
   }

// 使用类型别名作为对象的类型:
  let person: Person = {
      name: 'jack',
      gender:'男',
      score:30,
      height:180,
      study(){
       console.log("我不爱学习"); 
     },
   play(name){
      return "我有打" +name
    }
  }
console.log(person);

image.png

17.对象的可选属性

image.png

18.interface和type的区别:

 interface(接口)和 type(类型别名)的对比:
 相同点:都可以给对象指定类型
 不同点:
        接口,只能为对象指定类型
        类型别名,不仅可以为对象指定类型,实际上可以为任意类型指定别名
 推荐:能使用 type 就是用 type
 
 interface IPerson {
      name: string
      age: number
      sayHi(): void
    }

  // 为对象类型创建类型别名
     type IPerson = {
     name: string
     age: number
     sayHi(): void
   }

 // 为联合类型创建类型别名
  type NumStr = number | string    
  

image.png

19.接口继承

image.png

image.png

20.元组类型

 场景:在地图中,使用经纬度坐标来标记位置信息
 可以使用数组来记录坐标,那么,该数组中只有两个元素,并且这两个元素都是数值类型
 let position: number[] = [116.2317, 39.5427]
 使用 number[] 的缺点:不严谨,因为该类型的数组中可以出现任意多个数字
 更好的方式:`元组 Tuple`
 元组类型是另一种类型的数组,它确切地知道包含多少个元素,以及特定索引对应的类型
 let position: [number, number] = [39.5427, 116.2317]
解释:
  1.  元组类型可以确切地标记出有多少个元素,以及每个元素的类型
  2.  该示例中,元素有两个元素,每个元素的类型都是 number
  

image.png

21.类型推论

    在 TS 中,某些没有明确指出类型的地方,TS 的类型推论机制会帮助提供类型
    换句话说:由于类型推论的存在,这些地方,类型注解可以省略不写
发生类型推论的 2 种常见场景:
 1.  声明变量并初始化时
 2.  决定函数返回值时
 // 变量 age 的类型被自动推断为:number
   let age = 18
// 函数返回值的类型被自动推断为:number
  function add(num1: number, num2: number): number {
   return num1 + num2
 }
 推荐:能省略类型注解的地方就省略(~~偷懒~~,充分利用TS类型推论的能力,提升开发效率)
 技巧:如果不知道类型,可以通过鼠标放在变量名称上,利用 VSCode 的提示来查看类型
 

image.png

22.字面量类型

  使用模式:字面量类型配合联合类型一起使用
  使用场景:用来表示一组明确的可选值列表
  

image.png

image.png

image.png

23.枚举类型

基本使用

1. 枚举的功能类似于字面量类型+联合类型组合的功能,也可以表示一组明确的可选值
2. 枚举:定义一组命名常量。它描述一个值,该值可以是这些命名常量中的一个

image.png

数字枚举

image.png

字符串枚举

image.png

image.png

image.png

24.any 类型

image.png

image.png

25.类型断言

image.png

image.png

26.TypeScript泛型

 泛型是可以在保证类型安全前提下,让函数等与多种类型一起工作,从而实现复用,常用于:函数、接口、class 
 需求:创建一个 id 函数,传入什么数据就返回该数据本身(也就是说,参数和返回值类型相同)
     function id(value: number): number { return value }
 比如,id(10) 调用以上函数就会直接返回 10 本身。但是,该函数只接收数值类型,无法用于其他类型
 为了能让函数能够接受任意类型,可以将参数类型修改为 any。但是,这样就失去了 TS 的类型保护,类型不安全
 function id(value: any): any { return value }
 泛型在保证类型安全(不丢失类型信息)的同时,可以让函数等与多种不同的类型一起工作,灵活可复用

泛型函数

image.png

image.png

27.泛型函数小练习

 //需求: 创建一个根据长度创建数组的方法
 function createArr(length,item){
  const arr = []
   for(let i = 0; i < length; i++){
       arr.push(item)
   }
  return arr
 }
 createArr(3,'abc')
 createArr(4,100)

 --------------------------------------
  function createArr<T>(length:number,item:T):T[]{
     const arr = []
   for(let i = 0; i < length; i++){
     arr.push(item)
   }
    return arr
  }
  console.log(createArr<string>(3,'abc'))  //   ['abc','abc','abc']
  console.log(createArr<number>(4,100))   //    [100,100]
同上面是一样的题目

image.png

image.png

泛型传递多个类型 多个类型作为参数传递
  //定义一个函数,交换数组两项的位置
     function reverse(arr){
            return [arr[1],arr[0]]
     }

  --------------------------------
     function reverse<[T1,T2]>(arr:[T1,T2]):[T2,T1]{
            return [arr[1],arr[0]]
     }

      reverse<[number,string]>([1,'abc'])

28.泛型小练习

image.png