天天看點

5種在TypeScript中使用的類型保護

摘要:在本文中,回顧了TypeScript中幾個最有用的類型保護,并通過幾個例子來了解它們的實際應用。

本文分享自華為雲社群《如何在TypeScript中使用類型保護》,作者:Ocean2022。

類型保護是一種TypeScript技術,用于擷取變量類型資訊,通常使用在條件塊語句中。類型守衛是傳回布爾值的正常函數,接受一個類型并告訴TypeScript是否可以縮小到更具體的類型。類型保護具有唯一的屬性,可以確定測試的值是根據傳回的布爾值設定的類型。

TypeScript使用了一些内置的JavaScript操作符,比如typeof、instanceof和in操作符,這些操作符用于确定一個對象是否包含屬性。類型保護可以讓你指導TypeScript編譯器在特定的上下文中推斷出變量的特定類型,確定參數的類型與你所說的一緻。

類型保護通常用于縮小類型,它非常類似于特征檢測,允許您檢測值的正确方法、原型和屬性。是以,您可以輕松地找出如何處理該值。

有五種主要的方式來使用類型保護:

  • instanceof

    關鍵字
  • typeof

    關鍵字
  • in

    關鍵字
  • 等式收縮式保護器
  • 帶有謂詞的自定義類型保護

在本文中,我們将探索上面列出的 5 種方法。讓我們開始吧!

instanceof 類型保護

Instanceof

是一個内置類型保護器,可用于檢查一個值是否是給定構造函數或類的執行個體。有了這個類型保護,我們可以測試一個對象或值是否派生自一個類,這對于确定執行個體類型的類型很有用。

instanceof

類型保護的基本文法如下:

objectVariable instanceof ClassName;      

在下面的例子中,我們看到了一個

instanceof

類型保護的例子:

interface Accessory {
    brand: string;
  }
  class Necklace implements Accessory{
    kind: string;
    brand: string;
    constructor(brand: string, kind: string) {    
      this.brand = brand;
      this.kind = kind;
    }
  }
  class bracelet implements Accessory{
    brand: string;
    year: number;
    constructor(brand: string, year: number) {    
      this.brand = brand;
      this.year = year;
    }
  }
  const getRandomAccessory = () =>{
    return Math.random() < 0.5 ?
      new bracelet('cartier', 2021) :
      new Necklace('choker', 'TASAKI');
  }
  let Accessory = getRandomAccessory();
  if (Accessory instanceof bracelet) {
    console.log(Accessory.year);
  }
  if (Accessory instanceof Necklace) {
    console.log(Accessory.brand);    
  }      

上面的

getRandomAccessory

函數傳回一個

Necklace

bracelet

對象,因為它們都實作了

Accessory

接口。

Necklace

bracelet

的構造函數簽名是不同的,用

instanceof

比較兩個構造函數簽名可以有效地确定類型。

typeof 類型保護

typeof

類型保護是用來确定變量的類型。

typeof

的類型保護據說是非常有限和淺薄的。它隻能确定以下JavaScript能識别的類型:

  • Boolean
  • String
  • Bigint
  • Symbol
  • Undefined
  • Function
  • Number

對于這個清單之外的任何内容,typeof類型保護隻傳回object。

typeof

類型保護可以用以下兩種方式編寫:

typeof v !== "typename"
#or 
typeof v === "typename"      

typename

可以是字元串、數字、符号或布爾值。

在下面的示例中,

StudentId

有一個

string|number

類型聯合參數條目。我們看到,如果變量是

string

,則輸出

Student

,如果是

number

,則輸出

Id

typeof

類型保護符幫助我們從

x

參數中提取類型:

function StudentId(x: string | number) {
    if (typeof x == 'string') {
        console.log('Student');
    }
    if (typeof x === 'number') {
        console.log('Id');
    }
}
StudentId(`446`); //prints Student
StudentId(446); //prints Id      

in 類型保護

in

類型保護檢查對象是否具有特定的屬性,并使用該屬性區分不同的類型。它通常傳回一個布爾值,表示該屬性是否存在于該對象中。它用于其縮小範圍,以及檢查浏覽器支援。

in

類型保護的基本文法如下:

propertyName in objectName      

在下面的例子中,in類型守衛檢查 

house

 屬性是否存在。如果存在,則傳回布爾值true,如果不存在,則傳回false。

"house" in { name: "test", house: { parts: "door" } }; // => true
"house" in { name: "test", house: { parts: "windows" } }; // => true
"house" in { name: "test", house: { parts: "roof" } }; // => true
"house" in { name: "test" }; // => false
"house" in { name: "test", house: undefined }; // => true      

下面是

in

類型保護的另一個類似例子:

interface Pupil {
    ID: string;
  }
  interface Adult {
    SSN: number;
  }
  interface Person {
    name: string;
    age: number;
  }
  let person: Pupil | Adult | Person = {
    name: 'Britney',
    age: 6
  };
  const getIdentifier = (person: Pupil | Adult | Person) => {
    if ('name' in person) {
      return person.name;
    }
    else if ('ID' in person) {
      return person.ID
    }
    return person.SSN;
  }      

等式收縮保護器

等式收縮保護器檢查表達式的值。為了使兩個變量相等,兩個變量必須是同一類型的。如果一個變量的類型未知,但它等于另一個具有精确類型的變量,那麼Typescript會使用該已知變量提供的資訊來縮小第一個變量的類型:

function getValues(a: number | string, b: string) {
    if(a === b) {
        // this is where the narrowing takes place. narrowed to string
        console.log(typeof a) // string
    } else {
        // if there is no narrowing, type remains unknown
        console.log(typeof a) // number or string
    }
}      

如果變量

a

等于變量

b

,那麼兩者必須具有相同的類型。在這種情況下,Typescript把它縮小到字元串。如果沒有收縮,a的類型仍然不明确,因為它可以是數字或字元串。

帶有謂詞的自定義類型保護

建立一個自定義類型守衛通常是使用類型守衛的強大選項。當您通過自己編寫來建立自定義類型保護時,可以檢查的内容沒有限制。但是,如果自定義類型保護被錯誤地編寫,它可能會帶來很多錯誤。是以,精度是關鍵。

一個自定義類型保護的例子如下所示:

interface Necklace{
    kind: string;
    brand: string;
}
interface bracelet{
    brand: string;
    year: number;
}
type Accessory = Necklace | bracelet;

const isNecklace = (b: Accessory): b is Necklace => {
    return (b as Necklace).kind !== undefined
}
const Necklace: Accessory = {kind: "Choker", brand: "TASAKI"};
const bracelet: Accessory = {brand: "Cartier", year: 2021};
console.log(isNecklace(bracelet)) //Logs false
console.log(isNecklace(Necklace)) //Logs true      

在上面的代碼中,類型謂詞

b

Necklace

,這會讓TypeScript将類型縮減為

Necklace

,而不是隻傳回一個布爾值。

結尾

TypeScript類型保護有助于確定類型的值,改善整體的代碼流。在本文中,我們回顧了TypeScript中幾個最有用的類型保護,并通過幾個例子來了解它們的實際應用。

大多數時候,您的用例可以使用

instanceof

類型保護、

tyoeof

的類型保護或

in

類型保護來解決,然而,您可以在絕對必要的時候使用自定義類型保護。

點選關注,第一時間了解華為雲新鮮技術~

繼續閱讀