深入浅出TypeScript | 青训营笔记

39 阅读8分钟

一、为什么要学习TS

TypeScript VS JavaScript

TypeScript是JavaScript的超集,具有可选的类型并可以编译为纯JavaScript。从技术上讲TypeScript就是具有静态类型的 JavaScript 。

image.png

  • 强类型指的是程序中表达的任何对象所从属的类型都必须能在编译时刻确定。优点如下:

    • (1) 编译时刻能检查出错误的类型匹配,以提高程序的安全性;
    • (2) 可以根据对象类型优化相应运算,以提高目标代码的质量;
    • (3) 减少运行时刻的开销。
  • 静态类型指的是在创建一份数据(变量、参数、返回值等)时需要显式指明该数据的类型。通常情况下,这些数据的类型一旦被定义,在程序的整个生命周期也不再改变。

TypeScript带来了什么

image.png

TypeScript推荐

TS开源教程及应用:GitHub - dzharii/awesome-typescript: A collection of awesome TypeScript resources for client-side and server-side development. Write your awesome JavaScript in TypeScript

TS到JS在线编译:TypeScript: TS Playground - An online editor for exploring TypeScript and JavaScript (typescriptlang.org)

二、TypeScript基础

基础类型

  1. boolean、number、string
  2. undefined、null
  3. any、unknown、void
  4. never
  5. 数组类型 []
  6. 元组类型 tuple
类型描述
boolean表示逻辑值:true 和 false。
number双精度 64 位浮点值。它可以用来表示整数和分数。
string一个字符系列,使用单引号(')或双引号(")来表示字符串类型。反引号(`)来定义多行文本和内嵌表达式。
undefined用于初始化变量为一个未定义的值
null表示对象值缺失。
any声明为 any 的变量可以赋予任意类型的值。
unknow一种表示未知类型的类型
void用于标识方法返回值的类型,表示该方法没有返回值。
nevernever 是其它类型(包括 null 和 undefined)的子类型,代表从不会出现的值。
数组在元素类型后面加上[]:let arr: number[] = [1, 2];或者使用数组泛型:let arr: Array = [1, 2];
元组元组类型用来表示已知元素数量和类型的数组,各元素的类型不必相同,对应位置的类型需要相同。

其中,any 和 unknown 的主要区别在于类型检查的严格程度。any 允许对其进行任意操作,而 unknown 需要进行类型检查或类型断验后才能进行操作,从而提供了更强的类型安全性。在使用时,应尽量避免过度使用 any 类型,而是在可能的情况下使用 unknown 类型,并在需要时进行类型检查和类型断言,以提高代码的类型安全性。

函数基础

  • 定义:TS定义函数类型时要定义输入参数类型和输出类型
  • 输入参数:参数支持可选参数和默认参数。
  • 输出参数:输出可以自动推断,没有返回值时,默认为void类型
  • 函数重载:名称相同但参数不同,可以通过重载支持多种类型

函数重载:

  • 每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。

参数类型不同:

function disp(string):void; 
function disp(number):void;

参数数量不同:

function disp(n1:number):void; 
function disp(x:number,y:number):void;

参数类型顺序不同:

function disp(n1:number,s1:string):void; 
function disp(s:string,n:number):void;

interface

  • 定义:接口是为了定义对象类型

  • 特点:

    • 可选属性: ?(允许有这个属性,或者没有这个属性,但是不能够多添加属性,多添加还是会报错)
    • 只读属性: readonly
    • 可以描述函数类型
    • 可以描述自定义属性
  • 总结:接口非常灵活duck typing 函数类型接口实例:

interface encrypt {
	(key:  string, value: string): string;
}


var fun: encrypt = function (ket: string, value: string): string {
	//....
}

  • 定义:写法和JS差不多,增加了一些定义

  • 特点:

    • 增加了public、 private、 protected修饰符

    • 抽象类:

      • 只能被继承,不能被实例化
      • 作为基类,抽象方法必须被子类实现
  • interface约束类,使用implements关键字

类的定义方法:

class class_name { 
    // 类作用域
}

类可以包含以下几个模块(类的数据成员):

  • 字段 − 字段是类里面声明的变量。字段表示对象的有关数据。
  • 构造函数 − 类实例化时调用,可以为类的对象分配内存。
  • 方法 − 方法为对象要执行的操作。

image.png

  • public为类成员的默认可见性,被public修饰的成员可在class的内部和外部被访问。
  • 当我们不想直接暴露类的属性,想让类属性在子类进行一定的逻辑计算,通过子类暴露。或者想让类属性只能在同一子类内部访问时,可以使用protected关键字。
  • 被private修饰的成员只允许在类的内部访问,子类也不具备访问性。
  • class Student extends Person是子类Student对父类Person的继承。
  • let person = new Person("daming")是使用 new 关键字来实例化类的对象。

三、TypeScript进阶

高级类型

1、联合类型 |

由一组有序的成员类型构成,联合类型表示类型可以为若干类型之一,等同于运算符 ||,类似于数学运算中的加法。需要注意的是联合类型是通过联合类型字面量来定义的。

联合类型字面量

  • 联合类型由两个及以上的成员类型构成,成员类型通过竖线符号 "|" 分隔。
  • 成员类型可以为任意类型,例如:布尔类型、字符串类型、字符串数组类型、函数类型、[[空对象类型字面量]]类型、对象类型。

image.png

2、交叉类型 &

通过&符号将多个类型进行合并成一个类型,然后用type来声明新生成的类型。

查阅资料: 分为两个不同的场景使用: (1)合并接口类型:将多个接口类型合并成为一个类型是交叉类型的一个常见的使用场景。这样就能相当于实现了接口的继承.

type Person = {
	name: string;
  age: number;
} & {
	height: number;
  weight: number;
} & {
	id: number;
}

const person: Person = {
	name: "zhangsan",
  age: 18,
  height: 180,
  weight: 60,
  id: 123456
}

(2)合并联合类型:交叉类型另外一个常见的使用场景就是合并联合类型。可以合并多个联合类型为一个交叉类型,这个交叉类型需要同时满足不同的联合类型限制.

type A = "blue" | "red" | 996;
type B = 996 | 666;
type C = A & B;
const c: C = 996;

3、类型断言

  • 作用: 手动指定值的类型

  • 场景:有时候你会比 TS 更加明确一个值的类型,此时,可以使用类型断言来指定更具体的类型。

  • 格式:const 变量 = 值 as 类型

4、类型别名(type VS interface)

  • 定义:给类型起个别名

  • 相同点:

    • 都可以定义对象或函数
    • 都允许继承
  • 差异点:

    • interface是 TS 用来定义对象,type 是用来定义别名方便使用;

    • type 可以定义基本类型,interface 不行 ;

    • interface 可以合并重复声明,type 不行;

泛型

  • 定义:指在定义函数,接口或类的时候,不预先指定具体的类型,而在使用的时候,再指定类型的一种特性。
  • 语法:使用尖括号<T>表示,其中T可以被任意字母替换,它代表一种类型,在使用时需要将其替换为具体的类型。
  • 两种方法指定类型:
    • 1、定义要使用的类型
    • 2、通过TS类型判断,自动推导类型
  • 作用:临时占位,之后通过传来的类型进行推导。

image.png

泛型工具类型

基础操作符

  • typeof:获取类型
  • keyof:获取所有键

image.png

  • in:遍历枚举类型
  • T[K]:索引访问
  • extends:泛型约束

image.png

常用工具类型

image.png

四、TypeScript实战

声明文件

为什么需要

  • TypeScript 作为 JavaScript 的超集,在开发过程中不可避免要引用其他第三方的 JavaScript 的库。虽然通过直接引用可以调用库的类和方法,但是却无法使用TypeScript 诸如类型检查等特性功能。

步骤:

  • declare:想使用第三方库,需要使用 declare 关键字来定义它的类型,帮助 TypeScript 判断我们传入的参数类型对不对。(declare 定义的类型只会用于编译时的检查,编译结果中会被删除。)
declare var jQuery: (selector: string) => any;

jQuery('#foo');//运行结果:jQuery('#foo');

  • .d.ts:以 .d.ts 为后缀。
runoob.d.ts
  • @types:是一个 npm 包,包含了许多第三方库的声明文件。

    • 使用案例:TypeScript 没有找到 jquery 这个包的定义,你可以通过npm install @types/jquery安装相关声明,并将 jquery 声明为 module。
  • tsconfig.json:是 TypeScript 项目的配置文件,它包含了编译器的配置选项。

使用 "include" 和 "exclude" 属性

{
"compilerOptions" :{
"module" : "system",
"noImplicitAny" : true,
"removeComments" : true,
"preserveConstEnums" : true,
"outFile" : "../ ../ built/ local/tsc.js ",
"sourceMap": true
},
"include" : [ "src/**/*"]"exclude" : [ "node_modules""**/*.spec.ts"]
}

泛型约束后端接口类型

image.png

参考资料: 【1】TS进阶篇 | TS高级类型之字面量类型、联合类型、交叉类型 - 掘金 (juejin.cn)