TypeScript 类型保护与区分类型

类型保护与区分类型

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

从概念上讲,“区分类型”通常指的是在编程中明确地识别和处理不同的类型。
区分类型常常通过类型保护来实现。目的是为了在处理联合类型或可能具有多种类型的变量时,能够根据其实际的类型进行不同的操作。

typeof 类型保护

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

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类型保护是通过构造函数来细化类型的一种方式。
用于类实例的类型判断:运行时确定一个对象是否是某个类的实例。
示例:

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 操作符类型保护

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

示例:

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 是要断言的类型。

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值