常见的类型保护有如下几种:

  • typeof
  • 平等缩小(例如:===、!==)
  • instanceof
  • in

# 一、类型缩小

# 1、typeof 守卫

function padLeft(padding: number | string, input: string) {
  // typeof类型守卫👀
  if (typeof padding === 'number') {
    return ' '.repeat(padding) + input
  }
  return padding + input
}

# 2、范围缩小

  • 真值/等值缩小
// 真值缩小
function printAll(strs: string | string[] | null) {
  // 因为 typeof null 的结果为 'object'
  if (strs && typeof strs === 'object') {
    for (const s of strs) {
      console.log(s)
    }
  } else if (typeof strs === 'string') {
    console.log(strs)
  }
}
// 等值缩小 👀
function printAll(strs: string | string[] | null) {
  if (strs !== null) {
    if (typeof strs === 'object') {
      for (const s of strs) {
        console.log(s)
      }
    } else if (typeof strs === 'string') {
      console.log(strs)
    }
  }
}

printAll(['a', 'b', 'c'])
  • in 和 instanceof
// 1、in

// 定义
type Fish = { swim: () => void }
type Bird = { fly: () => void }

function move(animal: Fish | Bird) {
  if ('swim' in animal) {
    return animal.swim()
  }

  return animal.fly()
}
// 使用
const fish: Fish = {
  swim: function () {
    console.log('鱼儿会游泳')
  }
}
move(fish) // 传入回调函数
// 2、instanceof
function logValue(date: string | Date) {
  if (date instanceof Date) {
    console.log(date.getTime())
  } else {
    console.log(date.split(' '))
  }
}

logValue(Date()) // 字符串类型
logValue(new Date()) // Date类型

# 3、类型谓词 😢

  • 简单演示
// 缩小pet的范围
function isFish(pet: Fish | Bird): pet is Fish {
  return (pet as Fish).swim !== undefined
}
详细示例
type Fish = {
  name: string
  swim: () => void
}

type Bird = {
  name: string
  fly: () => void
}

// 获取pet
function getSmallPet(): Fish | Bird {
  let fish: Fish = {
    name: 'shrkey',
    swim: () => {}
  }
  let bird: Bird = {
    name: 'sparrow',
    fly: () => {}
  }

  return true ? bird : fish // 假设经过逻辑判断后得到的是bird
}

// 判断pet是什么
function isFish(pet: Fish | Bird): pet is Fish {
  return (pet as Fish).swim !== undefined // ture的话,pet的类型就是Fish
}

let pet = getSmallPet() // pet是bird

if (isFish(pet)) {
  pet.swim()
} else {
  pet.fly()
}

const zoo: (Fish | Bird)[] = [getSmallPet(), getSmallPet(), getSmallPet()]
const underWater1: Fish[] = zoo.filter(isFish)
const underWater2: Fish[] = zoo.filter(isFish) as Fish[]
const underWater3: Fish[] = zoo.filter((pet): pet is Fish => {
  if (pet.name === 'sharkey') return false
  return isFish(pet)
})

# 二、更多内容

# 1、受歧视的 Union

  前面我们解决的大都是简单的类型,那遇到联合类型(union)怎么办呢?

例如:下面的 cricle 和 square 联合类型

① 问题

interface Shape {
  kind: 'circle' | 'square'
  radius?: number
  sideLength?: number
}

function getArea(shape: Shape) {
  return Math.PI * shape.radius ** 2 // 报错:Object is possibly 'undefined'.
}

② 解决

  • 非空断言 !
interface Shape {
  kind: 'circle' | 'square'
  radius?: number
  sideLength?: number
}

function getArea(shape: Shape) {
  return Math.PI * shape.radius! ** 2
}
  • 分类 switch
interface Circle {
  kind: 'circle'
  radius: number
}

interface Square {
  kind: 'square'
  sideLength: number
}

type Shape = Circle | Square

function getArea(shape: Shape) {
  switch (shape.kind) {
    case 'circle':
      return Math.PI * shape.radius ** 2
    case 'square':
      return shape.sideLength ** 2
  }
}

# 2、never 类型

  never 类型可以用于穷尽性检查。

以上面的代码为例:

interface Circle {
  kind: 'circle'
  radius: number
}

interface Square {
  kind: 'square'
  sideLength: number
}

interface Triangle {
  kind: 'triangle'
  sideLength: number
}

type Shape = Circle | Square | Triangle

function getArea(shape: Shape) {
  switch (shape.kind) {
    case 'circle':
      return Math.PI * shape.radius ** 2
    case 'square':
      return shape.sideLength ** 2
    default:
      const _exhaustiveCheck: never = shape // 报错:Type 'Triangle' is not assignable to type 'never'.
      return _exhaustiveCheck
  }
}
更新于 : 8/7/2024, 2:16:31 PM