Skip to content

类型守卫

TypeScript 类型守卫(Type Guards) 是一种在代码运行时执行检查,从而让编译器在某个范围内收窄变量类型的方式。它的核心目标是:通过条件语句让 TS 更准确地推断变量类型

提示

类型守卫 只在条件分支内生效

typeof 守卫

用于 基本类型(string, number, boolean, symbol, bigint, undefined, function)。

ts
function printValue(value: string | number) {
  if (typeof value === "string") {
    console.log(value.toUpperCase()) // string 类型
  } else {
    console.log(value.toFixed(2)) // number 类型
  }
}

instanceof 守卫

用于 对象实例

ts
class Dog {
  bark() {}
}
class Cat {
  meow() {}
}

function animalSound(animal: Dog | Cat) {
  if (animal instanceof Dog) {
    animal.bark()
  } else {
    animal.meow()
  }
}

in守卫

用于检查对象是否包含某个属性。

ts
type Fish = { swim: () => void }
type Bird = { fly: () => void }

function move(animal: Fish | Bird) {
  if ("swim" in animal) {
    animal.swim()
  } else {
    animal.fly()
  }
}

自定义类型守卫(is)

自定义类型守卫就是你写一个函数,这个函数的返回值类型使用 类型谓词(Type Predicate) 来告诉 TS “如果这个函数返回 true,那参数就是某种类型”

  1. 返回值必须是布尔值(TS 不会去理解函数逻辑,只看你写的类型谓词)
  2. 类型守卫函数通常用 isXXX、hasXXX 命名,直观表示结果
  3. 和 typeof、instanceof 不同,自定义守卫适合 复杂对象接口联合类型
ts
const opt = Object.prototype.toString

export function isArray(obj: any): obj is any[] {
  return opt.call(obj) === '[object Array]'
}

export function isObject(obj: any): obj is { [key: string]: any } {
  return opt.call(obj) === '[object Object]'
}

export function isString(obj: any): obj is string {
  return opt.call(obj) === '[object String]'
}

export function isNumber(obj: any): obj is number {
  return opt.call(obj) === '[object Number]' && obj === obj
}
ts
//如果Object中存在数字,就保留两位数字,如果是字符串,则去除空格,如果是函数,则执行
function handleObject(arg: any) {
  if (isObject(arg)) {
    let val // 循环外声明变量可以节省空间
    Object.keys(arg).forEach((key) => {
      // for...in会遍历到原型
      val = arg[key]
      if (isNumber(val)) {
        arg[key] = val.toFixed(2)
      }
      if (isString(val)) {
        arg[key] = val.trim()
      }
      if (isFunction(val)) {
        val()
      }
    })
  }
}

判空守卫(可选链 + null 检查)

ts
function printLength(str?: string | null) {
  if (str != null) {
    console.log(str.length) // TS 知道 str 是 string
  }
}

文字类型守卫(字面量缩小)

ts
type Direction = "up" | "down" | "left" | "right"

function move(dir: Direction) {
  if (dir === "up") {
    console.log("向上")
  } else if (dir === "down") {
    console.log("向下")
  }
}