TS-类型保护


  • ts 默认在使用的时候 都是联合类型, 不能直接使用联合类型。

  • 识别类型,通过判断识别所执行的代码块,自动识别变量属性和方法,对不同的类型进行范围缩小

一.typeof类型保护

function getTypeof(val: number | string) {
  if (typeof val === "number") {
    val //number
  } else {
    val //string
  }
}

二.instanceof类型保护

class Dog {}
class Cat {}

function getInstance(clazz: { new (): Dog | Cat }) {
  return new clazz()
}
function getInstance1(clazz: new (...args: any[]) => Dog | Cat) {
  return new clazz()
}
let type = getInstance(Cat)
if (type instanceof Cat) {
  type //Cat
} else {
  type //Dog
}

三.in类型保护

interface Fish {
  swiming: string
}
interface Bird {
  fly: string
  leg: number
}
function getType(animal: Fish | Bird) {
  if ("swiming" in animal) {
    animal // Fish
  } else {
    animal // Bird
  }
}
  • Array.isArray确保一个变量是数组
// 确保一个变量是数组
function ensureArray<T>(input: T | T[]): T[] {
  // 类型来辨识
  if (Array.isArray(input)) {
    return input
  } else {
    return [input]
  }
}

四.可辨识联合类型

interface WarningButton {
  class: "warning"
}
interface DangerButton {
  class: "danger"
}
function createButton(button: WarningButton | DangerButton) {
  if (button.class == "warning") {
    button // WarningButton
  } else {
    button // DangerButton
  }
}

五. null 保护

const addPrefix = (num?: number) => {
  num = num || 0 // null 保护
  function prefix(fix: string) {
    return fix + num!.toFixed()
  }
  return prefix("$")
}

这里要注意的是 ts 无法检测内部函数变量类型

六.is自定义类型保护

interface Fish {
  swiming: string
}
interface Bird {
  fly: string
  leg: number
}
//工具方法中判断类型的方法 全部需要使用 is 语法
// ts的返回值类型 animal返回值true为Burd
function isBird(animal: Fish | Bird): animal is Bird {
  return "swiming" in animal // 必须是boolean
}
function getAniaml(animal: Fish | Bird) {
  if (isBird(animal)) {
    animal // Bird
  } else {
    animal // Fish
  }
}

七.完整性保护

interface ICircle {
  kind: "circle"
  r: number
}
interface IRant {
  kind: "rant"
  width: number
  height: number
}
interface ISquare {
  kind: "square"
  width: number
}
type Area = ICircle | IRant | ISquare
const isAssertion = (obj: never) => {
  throw new Error("error")
}
const getArea = (obj: Area) => {
  switch (obj.kind) {
    case "circle":
      return 3.14 * obj.r ** 2
    case "rant":
      return obj.height * obj.width
    case "square":
      return obj.width * obj.width
    default:
      return isAssertion(obj) // 必须实现所有逻辑
  }
}

文章作者: 高红翔
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 高红翔 !
  目录