TypeScript 类型保护与区分类型

类型保护与区分类型

在 TypeScript 中,类型保护是一种用于在运行时确定变量类型的机制,以便在特定的代码分支中进行更精确的类型操作。在处理联合类型或类型可能发生变化的情况下,确保代码的类型安全性和准确性。

从概念上讲,"区分类型"通常指的是在编程中明确地识别和处理不同的类型。

区分类型常常通过类型保护来实现。目的是为了在处理联合类型或可能具有多种类型的变量时,能够根据其实际的类型进行不同的操作。

typeof 类型保护

用于基本类型(如 numberstringbooleansymbol等)的判断。

typescript 复制代码
function processValue(value: number | string) {
  if (typeof value === "number") {
    // 这里 value 被确定为 number 类型
    console.log(value + 1);
  } else {
    // 这里 value 被确定为 string 类型
    console.log(value + "1");
  }
}

processValue(1); // 2
processValue("1"); // "11"

typeof类型保护 只有两种形式能被识别: typeof v === "typename"typeof v !== "typename"typename必须是 numberstringbooleansymbol

instanceof 类型保护

instanceof类型保护是通过构造函数来细化类型的一种方式。

用于类实例的类型判断:运行时确定一个对象是否是某个类的实例。

示例:

typescript 复制代码
class Animal {
  move() {
    console.log("The animal is moving.");
  }
}

class Dog extends Animal {
  run() {
    console.log("The dog is running!");
  }
}
class Cat extends Animal {
}

function doSomethingWithAnimal(animal: Animal) {
  if (animal instanceof Dog) {
    // 在这里,TypeScript 知道 animal 是 Dog 类型
    animal.run();
  } else {
    animal.move();
  }
}

let myDog = new Dog();
doSomethingWithAnimal(myDog); // The dog is running!

let myCat = new Cat();
doSomethingWithAnimal(myCat); // "The animal is moving."

在上述示例中,当 animal 被判断为 instanceof Dog 时,TypeScript 会将 animal 的类型细化为 Dog 类型,从而允许访问 Dog 类特有的方法。

instanceof的右侧要求是一个构造函数,TypeScript将细化为:

  1. 如果此构造函数的 prototype 属性的类型不是 any 类型,那么 TypeScript 会将其细化为该 prototype 属性的类型。
  2. 如果构造函数具有构造签名(即定义了如何创建实例的方式),那么会将构造签名所返回的类型也纳入考虑,形成一个联合类型。

instanceof 类型保护的原理是基于 JavaScript 中对象的原型链机制。只有当对象的原型链中包含了指定类的原型对象时,instanceof 才会返回 true

注意: instanceof 只适用于类创建的对象,对于普通的对象或者原始类型是不适用的。

in 操作符类型保护

用于检查对象是否具有特定的属性。

示例:

typescript 复制代码
interface Bird {
  fly(): void;
}

interface Fish {
  swim(): void;
}

function handleCreature(creature: Bird | Fish) {
  if ('fly' in creature) {
    // 这里 creature 被确定为 Bird 类型
    creature.fly();
  } else {
    // 这里 creature 被确定为 Fish 类型
    creature.swim();
  }
}

function getSmallPet1(): Fish | Bird {
  return {
    fly: () => console.log("fly")
  }
}

function getSmallPet2(): Fish | Bird {
  return {
    swim: () => console.log("swim")
  }
}
let pet1 = getSmallPet1();
handleCreature(pet1); // fly

let pet2 = getSmallPet2();
handleCreature(pet2); // swim

用户自定义的类型保护

用户自定义的类型保护函数是通过返回一个类型谓词来实现的。类型谓词的形式是 parameterName is Type ,其中 parameterName 是要检查的参数名称, Type 是要断言的类型。

把上面的示例改成自定义的类型保护:

typescript 复制代码
function isBird(creature: Bird | Fish): creature is Bird {
  return (creature as Bird).fly!== undefined;
}

function handleCreature(creature: Bird | Fish) {
  if (isBird(creature)) {
    creature.fly();
  } else {
    creature.swim();
  }
}

isBird 函数就是一个用户自定义的类型保护函数。它根据对象是否具有 fly 方法来判断传入的对象是否为 Bird 类型。
creature is Bird就是类型谓词。

每当使用一些变量调用 isBird 时,TypeScript会将变量缩减为那个具体的类型,只要这个类型与变量的原始类型是兼容的。

相关推荐
梦想CAD控件几秒前
网页CAD协同设计平台-生产级在线实时协同CAD引擎
前端·javascript·架构
Highcharts.js几秒前
React 开发实战:如何使用 useEffect 为 Highcharts 注入实时数据
前端·javascript·react.js·开发实战·实时数据·highcharts·轮询数据
喂哟咦22 分钟前
关于用codex两周写了一个epub阅读器这件事
前端·javascript
CDwenhuohuo36 分钟前
前端文件预览
开发语言·前端·javascript
Hello.Reader38 分钟前
Ubuntu 上正确安装 Kali 虚拟机、Docker 与 kail 工具指南
linux·ubuntu·docker
Restart-AHTCM1 小时前
AI 时代的大前端崛起,TypeScript 重塑前端开发
前端·人工智能·typescript·ai编程·a
008爬虫实战录1 小时前
【最新猿人学】 验证码 - 图文点选 文字验证码识别
前端·javascript
一袋米扛几楼981 小时前
【报错问题】解决 Vercel 部署报错:Express 类型失效与 TypeScript 2349/2339/2769 错误排查
ubuntu·typescript·express
一叶飘零晋1 小时前
【(一)Electron 使用之如何用vite+vue3搭建初始框架】
前端·javascript·electron
MIXLLRED2 小时前
Ubuntu22.04 + ROS2 Humble + RealSense D435i 部署VINS-Fusion视觉惯性SLAM
ubuntu·slam·d435i·ros2·humble·vins