前端专栏 2019-11-22 19:17:55

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

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

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

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

前言

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

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

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

类型声明

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

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

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

类型校验

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

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

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

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

一、基本类型

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

1.1 string

表示类型为字符串

1.2 number

表示类型为数字

1.3 boolean

表示类型为布尔类型

1.4 undefined

表示类型为 undefined

1.5 null

表示类型为 null

1.6 void

表示类型为 undefined 或 null。

1.6.1 对于变量

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

1.6.2 对于函数

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

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

1.7 never

表示永远不存在值。

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

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

1.8 any

表示可能为任何类型。

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

二、引用类型

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

2.1 数组类型

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

2.1.1 方括号表示法

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

2.1.2 尖括号表示法

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

2.2 只读数组

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

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

2.3 object

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

2.4 元组

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

2.5 枚举

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

三、类型断言

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

尖括号写法

as 写法

注意事项

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

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

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

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

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

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

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

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

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

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

四、接口

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

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

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

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

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

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

重写上述接口 ——

4.1 固定属性

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

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

4.2 可选属性

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

4.3 只读属性

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

4.4 额外检查

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

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

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

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

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

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

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

4.5 可索引类型

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

4.5.1 字符串索引类型

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

4.5.2 数字索引类型

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

4.5.3 混合索引签名

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

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

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

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

4.5.4 只读索引签名

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

4.6 函数类型

函数类型具有调用签名。

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

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

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

4.7 类类型

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

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

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

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

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

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

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

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

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

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

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

4.8 接口继承

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

4.9 混合类型

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

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

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

4.10 接口继承类

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

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

结语

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

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

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

一文学会 TypeScript 的 82% 常用知识点(上)的更多相关文章

  1. 一文学会 TypeScript 的 82% 常用知识点(下)

    一文学会 TypeScript 的 82% 常用知识点(下) 前端专栏 2019-11-23 18:39:08     都已经 9021 年了,TypeScript(以下简称 TS)作为前端工程师不得 ...

  2. DB2_SQL_常用知识点&实践

    DB2_SQL_常用知识点&实践 一.删除表中的数据(delete或truncate) 1 truncate table T_USER immediate; 说明:Truncate是一个能够快 ...

  3. JAVA常用知识点及面试题总结

    1. String.StringBuffer.StringBuilder三者区别? (1)三者在执行速率上的比较: String<StringBuffer<StringBuilder 原因 ...

  4. HTML常用知识点代码演示

    1 HTML部分常用知识点 <!-- 版本声明 --> <!DOCTYPE html> <!-- 唯一根元素 --> <html> <!-- 对网 ...

  5. Java 常用知识点

    Java 常用知识点 1.日期格式化 SimpleDateFormat Date date=new Date(System.currentTimeMillis()) ; SimpleDateForma ...

  6. Less常用知识点

    上篇文章介绍了如何安装Less,我们将所有东西都写在.less里面,最后通过命令将.less转换成.css文件,就可以放入到项目里用了.今天了解一些less常用知识点. 1.变量:声明两个变量,一个是 ...

  7. BIOS备忘录之EC常用知识点

    BIOS工程师眼中常用的EC知识点汇总: EC的硬件架构 EC硬件结构上主要分为两部分:Host Domain和EC Domain Host Domain就是通过LPC与CPU通信的部分(LPC部分需 ...

  8. YII2常用知识点总结

    YII2常用知识点总结 (一)总结性语句 (1)经常看看yii源码比如vendor\yiisoft\yii2\web这个目录(很重要)下的文件中的方法(这些文件中的公共方法,大致看了下基本上都可以通过 ...

  9. CSS3常用知识点

    CSS3常用知识点 1 css3选择器 1.1 属性选择器 /* E[attr~=val] 表示的一个单独的属性值 这个属性值是以空格分隔的*/ .attr2 a[class~="kawa& ...

随机推荐

  1. 一、VUE项目BaseCms系列文章:项目介绍与环境配置

    一.项目效果图预览: 二.项目介绍 基于 elementui 写一个自己的管理后台.这个系列文章的目的就是记录自己搭建整个管理后台的过程,希望能帮助到那些入门 vue + elementui 开发的小 ...

  2. Mysql增量备份之Mysqldump&Mylvmbackup

    简单介绍 备份类型 备份方式 热备份:备份期间不需要服务停机,业务不受影响: 温备份:备份期间仅允许读的请求: 冷备份:备份期间需要关闭Mysql服务或读写请求都不受影响: 完全备份:full bac ...

  3. 项目如何部署在linux系统上

    前面已经安装好centos的系统,网络配置,以及部署的环境已成功啦... 下面记录的是如何部署一个项目 四个步骤: (1)放war包 (2)执行数据库脚本 (3)修改数据库的配置文件 (4)重启tom ...

  4. 《DevOps实践:驭DevOps之力强化技术栈并优化IT运行》

    DevOps实践:驭DevOps之力强化技术栈并优化IT运行 主旨 这本书并非坐而论道,而是介绍了DevOps全流程中的许多实践,以及相应工具的运用.虽然随着时代的推移,工具将来可能会过时,但是这些实 ...

  5. SA详细注释不压行代码

    ){ //变量含义:m是字符集大小,n是字符串长度,c是一个桶数组,a[i]是字符串(下标从1开始) //rk[i]就是suffix(i)的字典序排名,sa[i]就是要求的排名为i的后缀的起始位置,即 ...

  6. android屏幕监视工具 android screen monitor使用

    android screen monitor是一个非常好用的手机屏幕监视工具,可以将你的手机界面动态的显示出来,可用于项目演示. 这个工具就是其实一个jar文件,不到300KB大小,依赖jdk,并且还 ...

  7. Maven項目打包報錯:Plugin execution not covered by lifecycle configuration

    Maven項目打包報錯:Plugin execution not covered by lifecycle configuration 使用Eclipse导入一个新的maven项目时不时的会遇到这个错 ...

  8. Redis入门(一)-Redis简介

    最近几年,Rddis非常的火,受到广大中大型公司,特别是互联网公司的青睐.而作为后端开发,如果你不知道Redis或不会用,没用过,你都不好意思出去找工作.可想而知Redis对于IT行业意义多么重大.对 ...

  9. [算法]实现strStr()

    题目 实现 strStr() 函数. 给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始).如果不存在 ...

  10. Ruby中星号打包解包操作

    Ruby中可以使用一个星号*和两个星号**完成一些打包.解包操作,它们称为splat操作符: 一个星号:以数组为依据进行打包解包(参考文章) 两个星号:以hash为依据进行打包解包(参考文章) 两个星 ...