在 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