TypeScript 如何做类型守卫

你有没有过这样的经历:写JavaScript时,明明给函数传了个“看起来对”的参数,运行时却突然报错“某某属性不存在”?比如你写了个打印信息的函数,给字符串能正常工作,给数字就直接崩了——这都是因为JS太“宽松”,啥类型都能塞。而TypeScript(简称TS)的类型守卫,就是帮你解决这类问题的小工具,能让类型判断变得简单又靠谱。

什么是类型守卫?

简单说,就是在代码里给TS当“类型裁判”。当你不确定某个值到底是什么类型时,它能帮你锁定类型,告诉TS“这一段里,这个值肯定是X类型”,这样后面的代码就不会乱报错。举个生活化的例子:你手里有个“包裹”,不知道里面是衣服还是零食,类型守卫就像你打开包裹看了一眼,确定是零食后,就可以直接拆包装袋吃;如果是衣服,就去叠衣服——不会拿着零食去洗,也不会拿着衣服去拆包装。

TypeScript 如何做类型守卫

最常用的3种类型守卫,看完就能用

typeof守卫:判断基本类型

这是最基础的守卫,专门用来判断string、number、boolean、undefined、symbol这些简单类型。比如你写了个处理用户输入的函数,输入可能是数字(年龄),也可能是字符串(昵称):

`typescript

function printInfo(input: string | number) {

// 这里的typeof就是守卫,确定input是string时,才能用字符串的toUpperCase方法

if (typeof input === 'string') {

console.log(input.toUpperCase())

} else {

// 剩下的就是number类型,直接用数字的toFixed方法

console.log(input.toFixed(1))

}

}

`

你传字符串“张三”,会输出“张三”全大写;传数字25,会输出“25.0”——要是没加typeof守卫,直接用toUpperCase,TS会提示“number没有这个方法”,再也不会凭空报错了。

instanceof守卫:判断对象类型

如果是判断对象,比如你有个Cat和Dog两个类,不确定传进来的是哪个,就用instanceof。比如你要写个喂宠物的函数:

`typescript

class Cat { meow() { console.log('猫叫') } }

class Dog { bark() { console.log('狗叫') } }

function feedPet(pet: Cat | Dog) {

// 用instanceof判断是不是Cat实例

if (pet instanceof Cat) {

pet.meow()

} else {

pet.bark()

}

}

`

你喂猫就会听猫叫,喂狗就会听狗叫——要是没加instanceof,TS不知道pet是啥,会不让你随便调用meow或bark方法。

in守卫:判断对象里有没有属性

要是你不确定一个对象里有没有某个属性,就用in守卫。比如你有两个接口,一个是带地址的用户,一个是不带地址的访客:

`typescript

interface User { name: string; address: string }

interface Guest { name: string }

function printContact(person: User | Guest) {

// in判断person里有没有address属性

if ('address' in person) {

console.log(地址:${person.address})

} else {

console.log('没有地址')

}

}

`

传带地址的用户,就会打印地址;传访客,就说没地址——这和你判断“快递单上有没有写地址”是一个道理。

用类型守卫的小提醒

别过度依赖守卫,它只是帮你明确类型,不是万能的。比如要是你传的参数是任意类型(any),最好先把它转成明确的联合类型,再用守卫,不然TS还是会懵。另外,守卫的判断要明确,比如写if (typeof input === 'string'),别写成if (typeof input !== 'number')——虽然逻辑上对,但TS的识别度会差一点,容易出问题。

其实类型守卫本质上是TS的“类型缩小”工具,把模糊的联合类型缩成明确的类型,让代码既安全又灵活。掌握这几个常用的守卫,就能解决80%的类型报错问题,写TS的时候不用再提心吊胆“会不会又崩了”。

上一篇 PHP 运算符有哪些