TypeScript

33 阅读9分钟

TypeScript

TypeScript 快速上手.pdf

装饰器.pdf

作用:JS可以进行全栈开发,应用场景丰富,代码量大,但由于出生简陋(当初诞生时的定位就是一个简单的脚本语言,用于网页内的简答逻辑),导致现在有很多问题

一、为何需要TypeScript

主要的困扰( 将index.js改成index.ts直接报错

1.数据类型不清楚

2.相同逻辑用了else if,js不会报错

3.访问不存在的属性,js不会标红报错

4.方法名写错,js不会标红报错,但在控制台会报错(大写应该是toUpperCase)

image

静态类型检查(运行前检查)

TS在代码** 运行前 **进行检查,发现错误就报错,减少运行时异常几率​ ** (JS只会在运行时报错) **

image

二、编译TypeScript

命令行编译(了解)

tsc的意思是typescript compiler

image

自动化编译

创建ts配置文件

image

这里target-es2016指的是es7,版本号为年份+1,那么es6为es2015

image

使用Vue、React这些官方提供的webpack/vite脚手架时,会自动将ts转换为js,不用管

三、类型声明

官方推荐类型为小写的,string、number等

image

函数的参数和返回值都可以设置类型限制

四、类型推断

如果没有规定类型,则TS会自动推导,但可能出问题,尽量定义类型

image

五、类型总览

image

image

知识点:

string(小写)为原始类型,String(大写)为包装对象---很少用

image

原始类型string不能使用构造函数,而包装对象String可以赋值字符串也可以使用构造函数

image

自动装箱解释

image

str没有length属性,但是可以执行,结果为5

因为此时str是字符串类型,JS会将str自动装箱为String类型,它有length属性,所以可以输出(也就表明包装对象更占内存空间

image

六、常用类型与语法

  1. any

    any(很少用):任意类型,即存什么都可以,不做类型检查

    let a: anylet a等价,不设置类型就是任意类型

    ** any类型的数据可以给任意类型的变量赋值 **

    image

  2. unknown

    unknown:未知类型,不知道具体存什么类型

    与any很类似,可以存任何类型,区别是** 不能赋值给非unknown类型的变量,更安全 **

    如何强行赋值?

    1.加类型判断

    2.使用断言

    x = a as string​​​​

    x = <string>a​​​​

    image

    image

    需要用断言!!!

  3. never

    never(很少用):什么值都没有,用于限制函数的返回值(用于抛出异常)

    不要将never用在变量上;never用在函数上不能有返回值,** 只能用于抛出异常函数 **,函数会停止运行(即没有任何返回值,包括undefined)

    TS也会自动推断出下面第一段程序中else中的a只有为never类型

    image

    image

  4. void

    void:空,函数不返回任何值,调用者不应依赖其返回值进行任何操作

    ** 如果没有return值,无显式返回值,但有隐式返回值undefined,return undefined就是void **

    以下三种都可以

    image

    void与undefined区别

    void类型函数可以返回undefined,void类型没有返回值,不能用其返回值进行后续判断,而undefined可以进行后续操作

    image

  5. object与Object

    object(很少用):限制太大,含义为所有非原始类型,比如对象、函数、数组等

    image

    Object(很少用):限制太大,所有可以调用Object方法的类型(即能调用.toString()方法的类型都可以,数值类型、字符类型、boolean类型)

    简单理解:除了undefined和null的任何值

    image

    开发中声明对象类型

    1.可选属性

    let person1: { name: string, age?: number }

    这里的 ?表示可选属性,声明时可有可无

    image

    2.索引签名

    不确定对象属性的数量时,可以用 [key: string]: any 表示可存在任意数量任意类型的其他属性

    image

    3.对象的简写形式

    对象中的a就等于1,b就等于2

    image

    开发中声明函数类型(还有其他形式,后续补充)

    let count: (a: number, b: number) => number

    参数a:number类型,b:number类型

    函数返回值:number类型

    image

    开发中声明数组类型

    image

  6. tuple

    tuple:元组(不能写let a : tuple)

    元组是一种特殊的数组类型,但不能声明tuple类型

    image

  7. enum

    enum(很重要):枚举

    开发中可能会遇到下面问题,有很多判断

    image

    数字枚举

    下标默认从0开始,这里Direction相当于一个类型

    image

    也可以自定义下标起始值

    image

    使用数字枚举完成之前walk函数逻辑

    不用关心Up是几,看名字即可

    image

    字符串枚举(用的少,api里面会用)

    image

    常量枚举

    使用const定义枚举,在TS编译时会将成员引用替换为实际值,例如下图中的x=0,不生成额外的枚举对象,可以减少JS代码量提高运行时性能

    使用普通枚举编译后JS代码

    image

    使用常量枚举编译后JS代码

    image

  8. type类型

    1. 基本用法:可以为任意类型创建别名

      image

    2. 联合类型(或|):多种类型的集合,可用字面量

      image

    3. 交叉类型(并&)

      type House = Area & Address

      这里的House类型需要包含Area和Address类型的所有属性

      image

  9. 一个特殊情况

    正常情况

    image

    特殊情况

    分两步走,先声明类型限制返回值为void,再给函数限制类型(** 这时TS不会严格要求函数返回值是否为空 **)

    image

    防止以下问题

    当箭头函数只有一句时,这里的push语句返回值是数组的长度,即number类型,而forEach方法接受的回调函数返回值为void类型,为了能让箭头函数正常执行官方才这么做的

    image

    image

    image

  10. 复习类相关知识

    类的声明和Java一样

    image

    继承extends
    1. 如果子类属性和父类一样,子类连构造器都不用写了
    2. 属性不一样时,用super(name,age)表示需要父亲的相同属性,这里用super表示调用父类的构造器,要写在构造器的第一行
    3. override表示重写从父类继承的方法

    image

  11. 属性修饰符

    当没有给类中属性和方法添加修饰符时,默认为public

    image

    public修饰符

    类的内部、子类、类外部访问

    image

    属性简写形式

    相当于不写属性,直接在构造器里面的参数填属性并加上public

    image

    protected修饰符

    类的内部和子类可以访问

    image

    private修饰符

    只能在类的内部访问

    image

    readonly修饰符

    只读属性,在属性前面加

    image

  12. 抽象类

    简单理解:抽象类无法被实例化,它可以写抽象方法,也可以写具体方法,抽象方法不能有具体实现,要由它的儿子来实现(不能有函数体,即花括号)

    例题:

    image

    这里的标准包裹类有自己的属性---单位价格,需要实现抽象方法,会用到这个单位价格

    创建实例时要用子类创建,因为抽象类无法被实例化

    image

    何时使用抽象类

    需要所有子类都实现关键行为

    image

  13. interface(接口)

    接口定义一种结构,确保代码的一致性和安全;接口只能定义格式,不能有任何实现 ** (抽象类可以有具体实现) **

    接口需要实现implements

    类实现接口

    image

    对象实现接口(这里接口相当于一个类型)

    image

    函数实现接口

    image

    接口之间的继承(相当于把父类的条件加进来了)

    image

    接口的合并性(可以重复定义)

    image

    何时使用接口?

    image

    interface和type的共同点和区别

    相同点:都可以定义对象的结构

    不同点:interface支持继承和合并;而type不支持,它可以定义类型别名、联合类型(|)、交叉类型(&)

    image

    interface和抽象类的共同点和区别

    相同点:都可以定义一个类的格式

    不同点:

    接口只描述结构,不能有任何实现,一个类可以实现多个接口

    抽象类可以包含抽象方法,也可以包含具体方法,一个类只能继承一个抽象类

    image

七、泛型-可以代表任意类型

第一个练习中三个T都是一种类型,当要传入数值类型时T就是number

第二个练习中函数的返回值是 T | U,即T或者U

image

泛型接口

image

泛型类

image

八、类型声明文件

.d.ts文件作用是让ts在使用js库时进行类型检查和提示

image

九、装饰器

装饰器一共有5种

  1. 类装饰器
  2. 属性装饰器
  3. 方法装饰器
  4. 访问器装饰器
  5. 参数装饰器

image

建议使用experimentalDecorators配置来开启对装饰器的支持

image

类装饰器(就是一个函数,可以将它以注解的形式写到类上)

基本语法

类似Java中的注解

image

应用举例

对象类型调用.toString方法返回的时[object Object],现在需要打印p的内容

image

下图的Object.seal(target.prototype)​可以封闭它的原型对象,使其无法修改

调用Person.prototype.x = 100​,修改其属性x的值会报错,如果没有上面的封闭操作,则可以修改

image

关于返回值

image

类装饰器只能返回类或者不返回

有返回值时:返回的类会替换被装饰的类(需要对象内容一致,方法可以不一样),即加了@Demo的类

image

无返回值时:则被装饰的类不会被替换

image

image

定义构造类型(约定构造函数)

这里定义Constructor类型,用于接收类;首先类可以实例化,且发的返回类型是对象,箭头函数不可以实例化

image

定义构造类型且指定它的静态参数(这里new后面的大括号前是冒号)

image

后面的听不懂,放弃了...