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

相关推荐
悦涵仙子37 分钟前
CSS中的变量应用——:root,Sass变量,JavaScript中使用Sass变量
javascript·css·sass
兔老大的胡萝卜38 分钟前
ppk谈JavaScript,悟透JavaScript,精通CSS高级Web,JavaScript DOM编程艺术,高性能JavaScript pdf
前端·javascript
cs_dn_Jie4 小时前
钉钉 H5 微应用 手机端调试
前端·javascript·vue.js·vue·钉钉
开心工作室_kaic5 小时前
ssm068海鲜自助餐厅系统+vue(论文+源码)_kaic
前端·javascript·vue.js
有梦想的刺儿5 小时前
webWorker基本用法
前端·javascript·vue.js
不是笨小孩i6 小时前
开源AI图片处理工具HivisionIDPhotos安装与证件照制作指南
ubuntu
清灵xmf6 小时前
TypeScript 类型进阶指南
javascript·typescript·泛型·t·infer
小白学大数据6 小时前
JavaScript重定向对网络爬虫的影响及处理
开发语言·javascript·数据库·爬虫
qq_390161776 小时前
防抖函数--应用场景及示例
前端·javascript
lihuhelihu7 小时前
第3章 CentOS系统管理
linux·运维·服务器·计算机网络·ubuntu·centos·云计算