前端专栏 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. AndroidStudio集成.so遇见的问题:关于java.lang.UnsatisfiedLinkError: Native method not found

    我调试的是串口程序,程序中需要继承.so文件,AndroidStudio中集成.so文件的方法是将存放.so的文件夹(通常这个文件夹名字是:armeabi)拷贝到app的libs文件夹中,然后在app ...

  2. 追踪SQL Server执行delete操作时候不同锁申请与释放的过程

    一直以为很了解sqlserver的加锁过程,在分析一些特殊情况下的死锁之后,尤其是并发单表操作发生的死锁,对于加解锁的过程,有了一些重新的认识,之前的知识还是有一些盲区在里面的.delete加锁与解锁 ...

  3. JavaScript-----7.循环

    1.循环 在JS中主要有以下三种类型的循环 for循环 while循环 do...while循环 2. for循环 2.1 语法结构如下: for (初始化变量: 条件表达式: 操作表达式) { // ...

  4. JS时间戳与时间字符串之间的相互转换

    时间字符串 转 时间戳 /** * 时间字符串 转 时间戳 * @param {String} time_str 时间字符串(格式"2014-07-10 10:21:12") * ...

  5. Spring afterPropertiesSet方法

    1.init-method方法,初始化bean的时候执行,可以针对某个具体的bean进行配置.init-method需要在applicationContext.xml配置文档中bean的定义里头写明. ...

  6. linux下录屏和回放工具script和scriptreplay

    读书是一个长见识的过程,以前偶尔会用到录屏的工具,很少用想系统的学习一下.最近看了linux shell脚本攻略,发现很多新东西是以前自己没有接触到的.比如,这个非常好用的录屏工具:script,这次 ...

  7. Linux下shell脚本实现mongodb定时自动备份

    MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功 ...

  8. os.path.isfile()的正确用法(正确用法)

    之前网上查找os.path.isfile( )的使用:发现有些是错误的,主要原因是,传入的参数是相对路径,不是绝对路径. 但是,经过我的实验发现:os.path.isfile( )需要传入的参数是绝对 ...

  9. 神探Python程序员,带你千里捉小三!(附详情代码)

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 王翔 清风Python PS:如有需要Python学习资料的小伙伴 ...

  10. 原生js对cookie的增删改查

    一.增 document.cookie = cname + "=" + cvalue + ";expires=" + expires + ";path ...