17. TypeScript 联合类型和类型保护
这节我将带大家学习一下 TypeScript 联合类型和相关的类型保护知识,需要注意的是,只有联合类型存在的情况下,才需要类型保护。普通的类型注解,并不需要我们这种特殊操作。那先来看一下什么是联合类型。
联合类型展示
所谓联合类型,可以认为一个变量可能有两种或两种以上的类型。用代码举个例子,声明两个接口Waiter
(服务员)接口和Teacher
(技师)接口,然后在写一个judgeWho
(判断是谁)的方法,里边传入一个animal
(任意值),这时候可以是Waiter
,也可能是Teacher
。所以我们使用了联合类型,关键符号是|
(竖线)。
interface Waiter { anjiao: boolean; say: () => {}; } interface Teacher { anjiao: boolean; skill: () => {}; } function judgeWho(animal: Waiter | Teacher) {}
通过这个简单的例子,你应该知道什么是联合类型了。
function judgeWho(animal: Waiter | Teacher) { animal.say(); }
但这时候问题来了,如果我直接写一个这样的方法,就会报错,因为judgeWho
不能准确的判断联合类型具体的实例是什么。
这时候就需要再引出一个概念叫做类型保护
,类型保护有很多种方法,这节讲几个最常使用的。
类型保护-类型断言
类型断言就是通过断言的方式确定传递过来的准确值,比如上面的程序,如果会anjiao
(按脚),说明他就是技师,这时候就可以通过断言animal as Teacher
,然后直接调用skill
方法,程序就不再报错了。同样如果不会按脚,说明就是不同的服务员,这时候调用say()
方法,就不会报错了。这就是通过断言的方式进行类型保护。也是最常见的一种类型保护形式。具体看代码:
interface Waiter { anjiao: boolean; say: () => {}; } interface Teacher { anjiao: boolean; skill: () => {}; } function judgeWho(animal: Waiter | Teacher) { if (animal.anjiao) { (animal as Teacher).skill(); }else{ (animal as Waiter).say(); } }
类型保护-in 语法
我们还经常使用in
语法来作类型保护,比如用if
来判断animal
里有没有skill()
方法。
这里你可以赋值上面的judgeWho()
方法,然后改一下名字,我这里改成了judgeWhoTwo()
方法,具体程序如下:
function judgeWhoTwo(animal: Waiter | Teacher) { if ("skill" in animal) { animal.skill(); } else { animal.say(); } }
这里的else
部分能够自动判断,得益于TypeScript
的自动判断。
类型保护-typeof 语法
先来写一个新的add
方法,方法接收两个参数,这两个参数可以是数字number
也可以是字符串string
,如果我们不做任何的类型保护,只是相加,这时候就会报错。代码如下:
function add(first: string | number, second: string | number) { return first + second; }
解决这个问题,就可以直接使用typeof
来进行解决。
function add(first: string | number, second: string | number) { if (typeof first === "string" || typeof second === "string") { return `${first}${second}`; } return first + second; }
像上面这样写,就不报错了。这样就可以继续开心的编写程序了。
类型保护-instanceof 语法
比如现在要作类型保护的是一个对象,这时候就可以使用instanceof
语法来作。现在先写一个NumberObj
的类,代码如下:
class NumberObj { count: number; }
然后我们再写一个addObj
的方法,这时候传递过来的参数,可以是任意的object
,也可以是NumberObj
的实例,然后我们返回相加值,当然不进行类型保护,这段代码一定是错误的。
function addObj(first: object | NumberObj, second: object | NumberObj) { return first.count + second.count; }
报错不要紧,直接使用instanceof
语法进行判断一下,就可以解决问题。
function addObj(first: object | NumberObj, second: object | NumberObj) { if (first instanceof NumberObj && second instanceof NumberObj) { return first.count + second.count; } return 0; }
另外要说的是,instanceof
只能用在类上。
总结
本文我们主要介绍四种类型保护的方式,每种方式都在不同场景中使用(还有一些不太常用的类型保护方式,我就不讲了),你需要自己深刻理解,多练习,在开发时才能灵活使用。
码云笔记 » 17. TypeScript 联合类型和类型保护