所谓联合类型,可以认为一个变量可能有两种或两种以上的类型。用代码举个例子,声明两个接口Waiter(服务员)接口和Teacher(技师)接口,然后在写一个judgeWho(判断是谁)的方法,里边传入一个animal(任意值),这时候可以能是Waiter,也可能是Teacher。所以我们使用了联合类型,关键符号是|(竖线)。
interface Waiter { anjiao: boolean; say: () => {}; } interface Teacher { anjiao: boolean; skill: () => {}; } function judgeWho(animal: Waiter | Teacher) {}通过这个简单的例子,你应该知道什么是联合类型了。
但这时候问题来了,如果我直接写一个这样的方法,就会报错,因为judgeWho不能准确的判断联合类型具体的实例是什么。
这时候就需要再引出一个概念叫做类型保护
类型断言就是通过断言的方式确定传递过来的准确值,比如上面的程序,如果会anjiao(按脚),说明他就是技师,这时候就可以通过断言animal as Teacher,然后直接调用skill方法,程序就不再报错了。同样如果不会按脚,说明就是不同的服务员,这时候调用say()方法,就不会报错了。这就是通过断言的方式进行类型保护。也是最常见的一种类型保护形式。具体看代码:
function judgeWho(animal:Waiter | Teacher){ if(animal.anjiao){ (animal as Teacher).skill(); }else{ (animal as Waiter).say(); } }我们还经常使用in语法来作类型保护,比如用if来判断animal里有没有skill()方法。
这里你可以赋值上面的judgeWho()方法,然后改一下名字,我这里改成了judgeWhoTwo()方法,具体程序如下:
function judgeWhoTwo(animal: Waiter | Teacher) { if ("skill" in animal) { animal.skill(); } else { animal.say(); } }先来写一个新的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语法来作。现在先写一个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 只能用在类上。这里我们介绍四种类型保护的方式,每种方式都在不同场景中使用(还有一些不太常用的类型保护方式,我就不讲了),你需要自己深刻理解。