詳解TypeScript中的類型保護(hù)
概述
在 TypeScript 中使用聯(lián)合類型時(shí),往往會(huì)碰到這種尷尬的情況:
interface Bird {
// 獨(dú)有方法
fly();
// 共有方法
layEggs();
}
interface Fish {
// 獨(dú)有方法
swim();
// 共有方法
layEggs();
}
function getSmallPet(): Fish | Bird {
// ...
}
let pet = getSmallPet();
pet.layEggs(); // 正常
pet.swim(); // ts 報(bào)錯(cuò)
如上所示,getSmallPet函數(shù)中,既可以返回 Fish 類型的對(duì)象,又可以返回 Bird 類型的對(duì)象。由于返回的對(duì)象類型不確定,所以使用聯(lián)合類型對(duì)象共有的方法時(shí),一切正常,但是使用聯(lián)合類型對(duì)象各自獨(dú)有的方法時(shí),ts 會(huì)報(bào)錯(cuò)。
那么如何解決這個(gè)問(wèn)題呢?最粗暴的方法當(dāng)然是將聯(lián)合類型轉(zhuǎn)換為 any,不過(guò)這種方法不值得提倡,畢竟我們寫(xiě)的是 TypeScript 而不是 AnyScript。
此時(shí),我們使用今天的主角——類型保護(hù),閃亮登場(chǎng),它可以完美的解決這個(gè)問(wèn)題。
孔乙己說(shuō)過(guò),茴香豆有四種寫(xiě)法,同理,實(shí)現(xiàn)類型保護(hù),也有四種寫(xiě)法。
類型斷言
類型斷言是最常用的一種類型保護(hù)方法,即直接指定類型。由于,TypeScript 中識(shí)別的類型大多是靠 TypeScript 的自動(dòng)類型推算算出來(lái)的,所以會(huì)出現(xiàn)上面所說(shuō)的那種問(wèn)題,即 TypeScript 不知道具體對(duì)象類型是什么,所以不確定有沒(méi)有聯(lián)合類型各自獨(dú)有的方法。
當(dāng)使用類型斷言直接指定類型時(shí),相當(dāng)于你讓 TypeScript 開(kāi)啟了上帝模式,可以直接知道具體類型是聯(lián)合類型中的那個(gè),此時(shí)再使用對(duì)象的獨(dú)有方法就符合 TypeScript 的推斷了。
interface Bird {
// 獨(dú)有方法
fly();
// 共有方法
layEggs();
}
interface Fish {
// 獨(dú)有方法
swim();
// 共有方法
layEggs();
}
function getSmallPet(): Fish | Bird {
// ...
}
let pet = getSmallPet();
pet.layEggs(); // 正常
// 通過(guò)鴨子類型來(lái)進(jìn)行判斷
if ((pet as Bird).fly) {
// 類型斷言
(pet as Bird).fly()
} else {
// 類型斷言
(pet as Fish).swim()
}
如果嫌棄通過(guò) as 來(lái)進(jìn)行類型斷言不夠上流,還可以使用類泛型的寫(xiě)法,即:
let pet = getSmallPet();
pet.layEggs(); // 正常
// 通過(guò)鴨子類型來(lái)進(jìn)行判斷
if ((<Bird>pet).fly) {
(<Bird>pet).fly()
} else {
(<Fish>pet).swim()
}
tips:友情提示,雖然使用類泛型寫(xiě)法進(jìn)行類型斷言看起來(lái)高端一些,但是由于在 tsx 中語(yǔ)法存在歧義,所以為了統(tǒng)一起見(jiàn),推薦使用 as 的方法進(jìn)行類型斷言。
in語(yǔ)法
在js中,我們經(jīng)常使用 in 語(yǔ)法來(lái)判斷指定的屬性是否在指定的對(duì)象或其原型鏈中。
同理,在 TypeScript 中,我們可以通過(guò)這種方法確認(rèn)對(duì)象類型。
interface Bird {
// 獨(dú)有方法
fly();
// 共有方法
layEggs();
}
interface Fish {
// 獨(dú)有方法
swim();
// 共有方法
layEggs();
}
function getSmallPet(): Fish | Bird {
// ...
}
let pet = getSmallPet();
pet.layEggs(); // 正常
// 使用 in 語(yǔ)法進(jìn)行類型保護(hù)
if ('fly' in pet) {
pet.fly()
} else {
pet.swim()
}
原理同類型斷言一樣,都是引導(dǎo) TypeScript 的類型推斷,確定對(duì)象類型。
instanceof 語(yǔ)法
當(dāng)聯(lián)合類型中使用的是 class 而不是 interface 時(shí),instanceof 語(yǔ)法就派上用場(chǎng)了,通過(guò) instanceof 語(yǔ)法可以區(qū)分不同的 class 類型。
class Bird {
// 獨(dú)有方法
fly() {};
// 共有方法
layEggs() {};
}
class Fish {
// 獨(dú)有方法
swim() {};
// 共有方法
layEggs() {};
}
function getSmallPet(): Fish | Bird {
// ...
}
let pet = getSmallPet();
pet.layEggs(); // 正常
// 使用 in 語(yǔ)法進(jìn)行
if (pet instanceof Bird) {
pet.fly()
} else {
pet.swim()
}
typeof 語(yǔ)法
typeof 語(yǔ)法不同于 in 語(yǔ)法以及 instanceof 語(yǔ)法,in 語(yǔ)法以及 instanceof 語(yǔ)法都是用來(lái)引導(dǎo)類型推斷進(jìn)行不同對(duì)象類型推斷,而 typeof 語(yǔ)法常用于基本類型的推斷(或者是聯(lián)合使用基本類型和對(duì)象類型)。
簡(jiǎn)而言之,當(dāng)使用 typeof 能夠區(qū)分聯(lián)合類型中的不同類型時(shí),即可使用它。
function getSmallPet(): number | string {
// ...
}
let pet = getSmallPet();
if (typeof pet === 'number') {
pet++
} else {
pet = Number(pet) + 1
}
總結(jié)
就如茴香豆的四種寫(xiě)法的本質(zhì)依然是茴香豆一樣,類型保護(hù)的四種寫(xiě)法的本質(zhì)也是一樣的,即,引導(dǎo) TypeScript 中的類型推斷將類型推斷的多選題變?yōu)閱芜x題,這就是類型保護(hù)的本質(zhì)。
以上就是詳解TypeScript中的類型保護(hù)的詳細(xì)內(nèi)容,更多關(guān)于TypeScript類型保護(hù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用clipboard.js實(shí)現(xiàn)復(fù)制功能的示例代碼
本篇文章主要介紹了使用clipboard.js實(shí)現(xiàn)復(fù)制功能的示例代碼,詳細(xì)介紹了clipboard.js插件的使用,有興趣的可以了解一下2017-10-10
javascript簡(jiǎn)單實(shí)現(xiàn)命名空間效果
這篇文章主要介紹了javascript簡(jiǎn)單的實(shí)現(xiàn)命名空間效果的方法。需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2014-03-03
第四篇Bootstrap網(wǎng)格系統(tǒng)偏移列和嵌套列
這篇文章主要介紹了Bootstrap網(wǎng)格系統(tǒng)偏移列和嵌套列的相關(guān)資料,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06
JS實(shí)現(xiàn)的小火箭發(fā)射動(dòng)畫(huà)效果示例
這篇文章主要介紹了JS實(shí)現(xiàn)的小火箭發(fā)射動(dòng)畫(huà)效果,涉及javascript基于時(shí)間函數(shù)的頁(yè)面元素屬性動(dòng)態(tài)變換實(shí)現(xiàn)運(yùn)動(dòng)效果相關(guān)操作技巧,需要的朋友可以參考下2018-12-12
javascript實(shí)現(xiàn)的上下無(wú)縫滾動(dòng)效果
這篇文章主要介紹了javascript實(shí)現(xiàn)的上下無(wú)縫滾動(dòng)效果,具有無(wú)縫滾動(dòng)及響應(yīng)鼠標(biāo)滑過(guò)停止?jié)L動(dòng)的功能,簡(jiǎn)便實(shí)用,需要的朋友可以參考下2016-09-09
JS實(shí)現(xiàn)可改變列寬的table實(shí)例
本文為大家詳細(xì)介紹下通過(guò)JS實(shí)現(xiàn)可改變列寬的table,具體的思路及代碼如下,感興趣的朋友可以參考下哈,希望對(duì)大家有所幫助2013-07-07
微信小程序文章詳情頁(yè)面實(shí)現(xiàn)代碼
這篇文章主要介紹了微信小程序文章詳情頁(yè)面實(shí)現(xiàn)代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-09-09
JS統(tǒng)計(jì)Flash被網(wǎng)友點(diǎn)擊過(guò)的代碼
JS統(tǒng)計(jì)Flash被網(wǎng)友點(diǎn)擊過(guò)的代碼...2007-05-05

