摘要:在本文中,回顧了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
類型保護來解決,然而,您可以在絕對必要的時候使用自定義類型保護。
點選關注,第一時間了解華為雲新鮮技術~