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会将变量缩减为那个具体的类型,只要这个类型与变量的原始类型是兼容的。

相关推荐
云白冰5 分钟前
hiprint结合vue2项目实现静默打印详细使用步骤
前端·javascript·vue.js
匹马夕阳1 小时前
详细对比JS中XMLHttpRequest和fetch的使用
开发语言·javascript·ecmascript
木卫二号Coding2 小时前
Docker-构建自己的Web-Linux系统-镜像webtop:ubuntu-kde
linux·ubuntu·docker
长风清留扬2 小时前
小程序开发实战项目:构建简易待办事项列表
javascript·css·微信小程序·小程序·apache
程序员_三木2 小时前
从 0 到 1 实现鼠标联动粒子动画
javascript·计算机外设·webgl·three.js
点点滴滴的记录2 小时前
Java的CompletableFuture实现原理
java·开发语言·javascript
web Rookie2 小时前
React 中 createContext 和 useContext 的深度应用与优化实战
前端·javascript·react.js
男孩122 小时前
react高阶组件及hooks
前端·javascript·react.js
SP八岐大兔3 小时前
Linux(Ubuntu/CentOS)配置开机自启动服务
linux·ubuntu·centos
hhzz3 小时前
vue前端项目中实现电子签名功能(附完整源码)
前端·javascript·vue.js