在 TypeScript 中检查运行时的对象类型

Migel Hewage Nimesha 2023年1月30日 2022年6月15日
  1. TypeScript 中的主要类型
  2. 在 TypeScript 中检查运行时的类类型
  3. 在 TypeScript 中检查运行时的接口类型
在 TypeScript 中检查运行时的对象类型

本文讨论如何在 TypeScript 运行时检查对象类型。

TypeScript 中的主要类型

TypeScript 是一种强类型语言。因此,它会在编译时检查类型,从而减少运行时错误。

在 TypeScript 中,我们有几种主要类型,如下所示。

  • 原始类型,例如字符串、数字和布尔值
  • 自定义类类型
  • 接口类型
  • 工会类型
  • 输入别名

在 TypeScript 中检查运行时的类类型

TypeScript 支持 EcmaScript 6 中的 class 关键字。它可用于以 OOP 方式编写代码。

让我们创建类 Engineer

class Engineer {
}

让我们添加一个方法,因为此类不包含任何属性或行为。

class Engineer {
    visitSite(): void {
        console.log("This is the Engineer class");
    }
}

假设我们有另一个类 Doctor,如下所示。

class Doctor {
    visitWard(): void {
        console.log("This is the Doctor class");
    }
}

EngineerDoctor 是两种用户定义的类型。在某些情况下,我们必须检查现有对象类型是否属于 EngineerDoctor 类。

这对于 TypeScript instanceof 运算符来说非常简单。

使用 instanceof 运算符检查类类型

它检查给定对象是 TypeScript 类的实例还是构造函数。它考虑多级继承来检查相关类是否出现在不同的级别。

如果找到匹配的类,它将返回 true;否则,它将输出 false

语法:

my_object instanceof my_custom_class_type

让我们使用这个运算符来区分 TypeScript 逻辑中的 EngineerDoctor 类。

首先,我们将创建一个新的检查函数 checkObjectType()

function checkObjectType(myObject) {
    if (myObject instanceof Engineer) {
        myObject.visitSite()
    }
    if (myObject instanceof Doctor) {
        myObject.visitWard()
    }
}

在上面的检查器函数中,我们检查了 myObject 的类。根据结果​​,我们将所属的类方法称为 visitSite()visitWard()

让我们从两个类中启动对象并将对象传递给 checkObjectType 方法。

let engineerObject: Engineer = new Engineer;
let doctorObject: Doctor = new Doctor;
checkObjectType(engineerObject);
checkObjectType(doctorObject);

输出:

TypeScript 运行时类型检查输出 1

正如预期的那样,TypeScript 为提供的每个对象识别正确的类。

在 TypeScript 中检查运行时的接口类型

instanceof 可用于检查给定实例是否属于某个类。但是,这不适用于 TypeScript 接口类型或类型别名。

在运行时,所有这些接口类型都消失了。因此,通常的 JavaScript typeof 运算符将输出作为 object

让我们定义两个接口,AirplaneCar,如下所示。

interface Airplane {
    hasWings() {
        console.log("2 wings");
    }
}

interface Car {
    hasWheels() {
        console.log("4 wheels");
    }
}

接下来,我们将创建一个 TypeScript 用户定义的类型保护来检查给定的对象是属于 Airplane 还是 Car 类型,并将对象缩小为兼容的类型。在这里,我们应该使用类型谓词作为返回类型。

类型谓词的语法:

my_parameter_name is custom_type

my_parameter_name 应该是传递给函数的当前参数。在这种情况下,custom_type 将是 AirplaneCar

让我们来定义这两个类型的守护。

function isAirplane(anyObject: any): anyObject is Airplane {
    return (anyObject as Airplane).hasWings() !=== undefined;
}

我们通过检查 hasWings() 方法是否可用于传递的对象 anyObject 来检查对象的形状是否等同于接口形状。然后,我们返回将对象缩小为 Airplane 类型的类型谓词。

我们可以类似地实现 isCar() 函数。

function isCar(anyObject: any): anyObject is Car {
    return (anyObject as Car).hasWheels() !=== undefined;
}

最后,我们可以实现 testType() 函数来测试代码。

let car: Car = {wheels: 4};
let flight: Airplane = {wings: 2};

function testType(obj: any) {
  if (isAirplane(obj)) {
    // 'obj' is narrowed to type 'Airplane'
    console.log("Airplane wings: "+ obj.wings);
  }
  else if (isCar(obj)) {
    // 'obj' is narrowed to type 'Car'
     console.log("Car wheels: "+ obj.wheels);
  }
}

testType(car);
testType(flight);

输出:

TypeScript 运行时类型检查输出 2

借助用户定义的类型保护,我们可以在运行时检查接口的确切类型。

Migel Hewage Nimesha avatar Migel Hewage Nimesha avatar

Nimesha is a Full-stack Software Engineer for more than five years, he loves technology, as technology has the power to solve our many problems within just a minute. He have been contributing to various projects over the last 5+ years and working with almost all the so-called 03 tiers(DB, M-Tier, and Client). Recently, he has started working with DevOps technologies such as Azure administration, Kubernetes, Terraform automation, and Bash scripting as well.

相关文章 - TypeScript Type