深入浅出TypeScript | 青训营笔记

210 阅读4分钟

简单认识TS

TS是什么,为什么有学的必要

image.png

即,JS本身是一个动态、弱类型的语言,在搭建大型项目时,很容易因为变量类型导致一些不容易被发现的错误。

引入TS,使得项目更清晰,实现了类型安全,同时扩展了下一代JS的用法,提供了完善的工具链。

TS开源教程:awesome-typescript

TS在线编译(生成对应的JS文件):TypeScript: TS Playground

TS基础

基本变量:

  • number、boolean、string
  • any、unknown、void
  • 枚举enum(ts特有,映射和反映射

image.png

  • never(永远不存在值)

image.png

  • 数组类型[]
  • 元组类型tuple

关于 any、unknown、void

any:任意类型的变量

unknown:一个安全的但未知的变量,可以赋给unknown, any

void:用于表示函数不返回值

函数类型

function add(x: number[]): number
function add(x: string[]): string
function add(x: any[]): any {
    if (typeof x[0] === 'string') {
        return x.join();
    }
    if (typeof x[0] === 'number') {
        return x.reduce((pre, cur) => pre + cur)
    }
}
复制代码

需要定义形参的变量类型,函数的返回值类型

可以重载(名称相同,形参、返回值类型不同)

接口

定义对象类型

声明一个规范,使用接口的对象必须满足这些规范

设置规范的特点:

  • 可选属性 a?: number
  • 只读属性 readonly a: number
interface Person {
    name: string,
    age: number
}

加入了与C++相似的 public protected private 修饰符

用于规定访问变量的权限

public 可以在任意位置访问

protected 可以在类、子类、同一个包中访问

private 仅在同类中访问

同时引入 C++ 抽象类

abstract class Animal { //定义一个抽象类
    abstract name: string //一个抽象属性
    age: number //这是一个普通属性
    abstract eat(): void //一个抽象方法
    run(): void { //这是一个普通方法 }
}

含有抽象属性或抽象方法的类是抽象类。

  • 抽象属性:只定义变量名和变量类型,不允许赋值。
  • 抽象方法:只定义函数名、参数及其类型、返回值的类型,不做实现。

抽象类不能实例化,继承抽象类的子类必须实例化抽象类中的所有抽象变量和抽象方法

即,抽象类是一种类要实现的内容的规范。(描述了类要包含什么属性、为类要实现的方法指定接口)

继承抽象类的子类即,对应规范的具体实现。

与接口的对比:

  • 继承抽象类 extends
  • 实现接口 implements

高级类型

联合类型 |、交叉类型&

联合类型:允许一个变量存储多种类型的值

let num: number | string

交叉类型:用于合并多个接口,通常用于规范对象

interface Person {
    name: string,
    age: number
}
interface Lesson {
    classid: number
}

type Student = Person & Lesson

// 等效于
interface Student {
    name: string,
    age: number,
    classid: number
}

交叉类型类似于接口的继承,但是,当接口有冲突时,使用继承会报错,但使用交叉类型会合并。

interface Ia {
    foo(x: number): number
}
interface Ib {
    foo(b: string): number
}

type Ic = Ia & Ib
// 等效于
interface Ic {
    foo(x: number | string): number
}

类型断言

即先假定变量是某一类型,使得在访问其中属性时,编译器不报错。

在使用联合类型时,对于可能有多种类型的变量,在不确定具体类型时,直接使用其属性,会报错。因此,使用断言,先告诉解析器,此变量的类型。

属性前置的断言定义:

function getLength(x: string | number): number {
    return x.length;
    //此时,编译器不知道x是否是string,不能确定有length属性,因此报错
}
复制代码

使用类型断言 as 解决冲突:

function getLength(x: string | number): number {
    const str = x as string; // 先用断言,假定x是string类型
    if( str.length ) {
        return x.length
    }
    else {
        const num = str as number; //此时,确认x是number类型
        return num.toString().length
    }
}

类型别名

image.png

类似于C++的 typedef 将一种类型起别名

interface 的比较:

type 主要用于给基本类型(也包括函数)起别名,重复声明会被覆盖interface 用于类的规范,重复声明会合并

type 可以通过 &type合并

interface 可以通过 extends 继承 interface

此外, type 可以通过 in 遍历,interface不行

组合和交叉类型的时候使用type 涉及类,定义对象和函数,使用interface

泛型

应用场景

打印string->打印numer->打印任何类型

image.png 使用类型占位符,输入具体类型时,再确定。

基本语法

image.png 常用的运算符:

image.png

image.png

Ts实战

image.png