• 一文学会 TypeScript 的 82% 常用知识点(上)


    一文学会 TypeScript 的 82% 常用知识点(上)

     

    对于前端从业者来说,TypeScript(以下简称 TS)已经不算是新技术。

    Vue3 的源码基于 TS 编写, Angular 项目默认支持 TS 等。它出现的频率越来越高,而学习难度并不大,大概一个周末可以熟悉。

    投入少,产出大,所以最好还是花点时间学习一下。

    本文根据 TS handbook 整理出 TS 关键的知识点,并对某些部分作了扩展,希望能帮助大家学习理解。

    前言

    在学习 TS 之前,需要理解它的两个特点:

    1. TS 是 JS 的超集
    2. TS 给 JS 带来类型系统

    这意味着 TS 的根基是 JS,是在 JS 的 基础上添加了类型系统。

    类型声明

    类型系统的一个特点是使用类型声明。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    观察上述代码,在 JS 中,使用「等号=」给变量赋值。

    经过 TS 的扩展,可以使用「冒号:」给变量赋类型。代码中声明变量 foo 的类型是 string。

    类型校验

    类型系统的另一个特点是进行类型校验。

    在 TS 中,需要校验「等号=」左右的类型是否匹配。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    如上述代码所示,值存在明确的类型,TS 会校验左右两侧的类型是否匹配,若不匹配则提示错误。

    在了解这些前置知识后,来看看具体的 TS 知识点。

    一、基本类型

    继承 JS 的基本类型如:string、number、boolean、undefined、null。扩展了其他基本类型如:any、never、void。

    1.1 string

    表示类型为字符串

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    1.2 number

    表示类型为数字

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    1.3 boolean

    表示类型为布尔类型

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    1.4 undefined

    表示类型为 undefined

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    1.5 null

    表示类型为 null

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    1.6 void

    表示类型为 undefined 或 null。

    1.6.1 对于变量

    一个声明为 void 类型的变量,只能被赋值为 undefined 或 null。这种应用场景较少。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    1.6.2 对于函数

    void 用于表示函数没有返回值,只是执行某些操作。这是 void 的普遍应用场景。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    一个没有显式返回的函数,默认 return undefined。符合 void 类型只能被赋值为 undefined 或 null。

    1.7 never

    表示永远不存在值。

    典型例子:一个只会抛出异常的函数,它的返回值并不存在。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    执行函数则抛出错误,连 undefined 都不会返回。

    1.8 any

    表示可能为任何类型。

    典型例子:不确定变量的类型或类型是动态的。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    二、引用类型

    TS 中的引用类型,除了 JS 中的数组类型、对象类型,还扩展了枚举类型,元祖类型。

    2.1 数组类型

    表示由某(些)类型组成的数组。有两种写法:方括号表示法和尖括号表示法。

    2.1.1 方括号表示法

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    表示 arr 的类型是由数字组成的数组。

    2.1.2 尖括号表示法

    使用 Array<元素类型>,这是数组泛型的使用形式,关于泛型后续会展开。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    2.2 只读数组

    使用 ReadonlyArray<属性类型> 定义只读数组。只读数组只能在数组初始化时定义其值,创建后不能进行修改。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    只读数组和常规数组类型 Array<T> 类似。区别在于:常规数组存在修改数组的方法,只读数组不存在修改数组的方法。

    2.3 object

    表示类型为对象。除了 string、number、bigint、boolean、 undefined、null、symbol 基本类型外的引用类型。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    2.4 元组

    由定长数组构成,数组中的元素是某(些)类型。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    2.5 枚举

    使用关键字 enum 定义枚举类型。默认枚举值从 0 开始,可以手动赋值。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    三、类型断言

    明确告诉 TS 某个值的类型。有两种写法:尖括号写法、as 写法。

    尖括号写法

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    as 写法

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    注意事项

    类型断言和类型转换是有明确区别,不能将它理解成类型转换。

    在阐述此注意事项之前,先引入另一个概念:联合类型。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    在上述代码中,string | number 表示的就是一个联合类型,意味着 answer 的类型可以为 string 或 number。

    下面逐步解释类型断言和类型转换之间的区别。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    上述代码中,string | number 联合类型包含 string 类型,所以这两种类型之间存在联系。使用 as 将联合类型断言成更加具体的 string 类型。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    上述代码中,将 number 类型断言为 string | number 类型。同样是因为两种类型之间存在联系,所以也允许断言。相当于将一个具体的 number 类型断言成更加广泛的联合类型。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    而将 string 类型断言为 number 类型,这是两种不同的类型,没有任何联系,断言会提示错误。

    观察上述三个例子,断言发生在两种类型存在联系的情况,它并不是将一种类型转换成另一种类型。

    有些脑瓜子灵活的朋友会想到,借助两次断言来进行类似的类型转换。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    这是欺骗了 TS 校验,后果只能自己承担。

    四、接口

    上面提到使用 object 描述对象类型。但是,对于具有复杂结构的对象、函数。上述的 object 类型力有不逮。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    上述代码中,即使是空对象,也能通过 object 类型校验,而不会校验对象的结构是否能满足后续使用。

    此时,就需要使用接口。在 TS 中,接口是描述值的结构。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    上述代码中,就定义了一个接口来描述参数 o,要求它是一个对象,含有 name 属性,且属性值是字符串。

    所以,不符合此结构的空对象 {} 就提示错误。

    一般来说,使用关键字 interface 来定义接口。

    重写上述接口 ——

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    4.1 固定属性

    在接口中,使用 属性名:属性类型 的结构定义固定属性。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    如上述代码所示,传入的对象需要具有 name 和 age 两个属性,否则会报错。

    4.2 可选属性

    在接口中,使用 属性名?:属性类型 的结构定义可选属性。顾名思义,可选属性可以存在,也可以不存在。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    4.3 只读属性

    在接口中,使用 readonly 属性名:属性类型 的结构定义只读属性。只读属性只能在属性初始化时定义其值,定义后不能进行修改。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    4.4 额外检查

    TS 会对对象字面量进行额外的属性检查。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    在上述代码中,接口 Point 定义了两个可选属性,对象字面量中属性 x 和接口兼容,属性 z 是多余无意义的。

    虽然实际的属性比接口定义的多,按照常规理解,这是可以通过类型校验,但事实却相反。

    TS 对于对象字面量是会进行额外的属性检查,体现在:

    当对象字面量赋值给变量或它直接作为参数传递给函数时,如果对象字面量的属性没有在接口中定义,则会报错。

    换句话说,对于对象字面量,当它直接赋值给变量和函数参数时,它的属性不能比接口描述的多。

    这里重点是直接赋值,如果像例子中,先将对象字面量赋值给变量,再通过变量传参,这样间接的方法可以绕过额外的检查。

    4.5 可索引类型

    可索引类型包括字符串索引类型与数字索引类型。

    4.5.1 字符串索引类型

    字符串索引类型具有字符串索引签名。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    4.5.2 数字索引类型

    数字索引类型具有数字索引签名

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    4.5.3 混合索引签名

    属性和索引签名可以形成混合索引签名,但是属性需要和索引签名类型匹配。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    另外,TS 允许同时使用上述两种签名,但是数字索引返回值的类型,它必须是字符串索引返回值类型的子类型。

    因为对于 JS 来说,当使用数字索引时,会将它转换成字符串进行索引。所以它们需要保持一致。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    上述代码中,ThreeD 是 TwoD 的子类型,所以接口 PointA 正确。

    4.5.4 只读索引签名

    可以将索引签名设置为只读,只能在数组初始化时定义其值,创建后不能进行修改。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    4.6 函数类型

    函数类型具有调用签名。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    如上述代码所示,调用签名包括参数列表和返回值类型。

    对于函数类型来说,它校验的值当然是函数 ——

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    如上述代码所示,函数的参数名可以与签名的参数名不同。关键是对应位置的参数类型需要相同。

    4.7 类类型

    这里的概念有些复杂,如果有良好的 JS 基础,会较易理解。

    类的关键字是 Class,由 ES6 开始引入,并逐步完善。本质上 Class 属于语法糖,是基于 prototype 原型链实现的。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    而无论是 ES5 或 ES6,属性 age 是在创建的实例上,而方法 getAge() 是在实例的原型链上。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    而类本身,它是不存在 age 属性 和 getAge() 方法的。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    当然,我们也可以给类本身定义属性和方法。 但给类本身定义的属性和方法并不能通过实例直接访问。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    所以,类与实例的属性和方法是割裂的。

    TS 将描述类的属性和方法部分称为类的静态部分类型,将描述实例的属性和方法部分称为类的实例部分类型。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    在上述代码中,使用关键字 implements 描述类实现了接口。更准确的是:描述 类的实例部分 实现了接口。

    实现该接口的类的实例,它是具有 age 属性,getAge() 方法。而类本身(即类的静态部分)具有何种属性与方法,上述代码没有进行定义。

    所以,这里所说的类类型,实际上是类(实例的)类型。

    关于如何定义类的静态部分的类型,在后续会详细介绍。

    4.8 接口继承

    接口的可以使用关键字 extends 定义继承。一个接口可以继承多个接口。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    4.9 混合类型

    一个对象可能混合多种类型。

    例如定义一个带版本号的函数——

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    值得注意,上述使用类型断言,将函数断言为 Fn,即使 fn 在创建时并不存在 version 属性。

    4.10 接口继承类

    当接口继承类类型时候,表现在继承类的成员和结构,但不包括其实现。

    接口继承类的一个场景是,定义一个子类的类类型。

    一文学会 TypeScript 的 82% 常用知识点(上)

     

    结语

    由于文章篇幅问题,全文拆分成上下两篇发布。

    本篇主要介绍了 TS 的基本类型,引用类型、类型断言、接口等知识点,了解上述的知识点可以阅读部分 TS 代码。

    下篇涉及函数、类、泛型等稍微复杂的知识点。

  • 相关阅读:
    06-图3 六度空间 (30 分)
    06-图2 Saving James Bond
    06-图1 列出连通集 (25 分)
    05-树9 Huffman Codes (30 分)
    05-树8 File Transfer (25 分)
    05-树7 堆中的路径 (25 分)
    04-树6 Complete Binary Search Tree (30 分)
    04-树5 Root of AVL Tree (25 分)
    03-树3 Tree Traversals Again (25 分)
    只允许输入数字的TextBox控件
  • 原文地址:https://www.cnblogs.com/sexintercourse/p/11961086.html
Copyright © 2020-2023  润新知