詳解TypeScript中的類型保護
概述
在 TypeScript 中使用聯(lián)合類型時,往往會碰到這種尷尬的情況:
interface Bird { // 獨有方法 fly(); // 共有方法 layEggs(); } interface Fish { // 獨有方法 swim(); // 共有方法 layEggs(); } function getSmallPet(): Fish | Bird { // ... } let pet = getSmallPet(); pet.layEggs(); // 正常 pet.swim(); // ts 報錯
如上所示,getSmallPet函數(shù)中,既可以返回 Fish 類型的對象,又可以返回 Bird 類型的對象。由于返回的對象類型不確定,所以使用聯(lián)合類型對象共有的方法時,一切正常,但是使用聯(lián)合類型對象各自獨有的方法時,ts 會報錯。
那么如何解決這個問題呢?最粗暴的方法當(dāng)然是將聯(lián)合類型轉(zhuǎn)換為 any,不過這種方法不值得提倡,畢竟我們寫的是 TypeScript 而不是 AnyScript。
此時,我們使用今天的主角——類型保護,閃亮登場,它可以完美的解決這個問題。
孔乙己說過,茴香豆有四種寫法,同理,實現(xiàn)類型保護,也有四種寫法。
類型斷言
類型斷言是最常用的一種類型保護方法,即直接指定類型。由于,TypeScript 中識別的類型大多是靠 TypeScript 的自動類型推算算出來的,所以會出現(xiàn)上面所說的那種問題,即 TypeScript 不知道具體對象類型是什么,所以不確定有沒有聯(lián)合類型各自獨有的方法。
當(dāng)使用類型斷言直接指定類型時,相當(dāng)于你讓 TypeScript 開啟了上帝模式,可以直接知道具體類型是聯(lián)合類型中的那個,此時再使用對象的獨有方法就符合 TypeScript 的推斷了。
interface Bird { // 獨有方法 fly(); // 共有方法 layEggs(); } interface Fish { // 獨有方法 swim(); // 共有方法 layEggs(); } function getSmallPet(): Fish | Bird { // ... } let pet = getSmallPet(); pet.layEggs(); // 正常 // 通過鴨子類型來進行判斷 if ((pet as Bird).fly) { // 類型斷言 (pet as Bird).fly() } else { // 類型斷言 (pet as Fish).swim() }
如果嫌棄通過 as 來進行類型斷言不夠上流,還可以使用類泛型的寫法,即:
let pet = getSmallPet(); pet.layEggs(); // 正常 // 通過鴨子類型來進行判斷 if ((<Bird>pet).fly) { (<Bird>pet).fly() } else { (<Fish>pet).swim() }
tips:友情提示,雖然使用類泛型寫法進行類型斷言看起來高端一些,但是由于在 tsx 中語法存在歧義,所以為了統(tǒng)一起見,推薦使用 as 的方法進行類型斷言。
in語法
在js中,我們經(jīng)常使用 in 語法來判斷指定的屬性是否在指定的對象或其原型鏈中。
同理,在 TypeScript 中,我們可以通過這種方法確認對象類型。
interface Bird { // 獨有方法 fly(); // 共有方法 layEggs(); } interface Fish { // 獨有方法 swim(); // 共有方法 layEggs(); } function getSmallPet(): Fish | Bird { // ... } let pet = getSmallPet(); pet.layEggs(); // 正常 // 使用 in 語法進行類型保護 if ('fly' in pet) { pet.fly() } else { pet.swim() }
原理同類型斷言一樣,都是引導(dǎo) TypeScript 的類型推斷,確定對象類型。
instanceof 語法
當(dāng)聯(lián)合類型中使用的是 class 而不是 interface 時,instanceof 語法就派上用場了,通過 instanceof 語法可以區(qū)分不同的 class 類型。
class Bird { // 獨有方法 fly() {}; // 共有方法 layEggs() {}; } class Fish { // 獨有方法 swim() {}; // 共有方法 layEggs() {}; } function getSmallPet(): Fish | Bird { // ... } let pet = getSmallPet(); pet.layEggs(); // 正常 // 使用 in 語法進行 if (pet instanceof Bird) { pet.fly() } else { pet.swim() }
typeof 語法
typeof 語法不同于 in 語法以及 instanceof 語法,in 語法以及 instanceof 語法都是用來引導(dǎo)類型推斷進行不同對象類型推斷,而 typeof 語法常用于基本類型的推斷(或者是聯(lián)合使用基本類型和對象類型)。
簡而言之,當(dāng)使用 typeof 能夠區(qū)分聯(lián)合類型中的不同類型時,即可使用它。
function getSmallPet(): number | string { // ... } let pet = getSmallPet(); if (typeof pet === 'number') { pet++ } else { pet = Number(pet) + 1 }
總結(jié)
就如茴香豆的四種寫法的本質(zhì)依然是茴香豆一樣,類型保護的四種寫法的本質(zhì)也是一樣的,即,引導(dǎo) TypeScript 中的類型推斷將類型推斷的多選題變?yōu)閱芜x題,這就是類型保護的本質(zhì)。
以上就是詳解TypeScript中的類型保護的詳細內(nèi)容,更多關(guān)于TypeScript類型保護的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用clipboard.js實現(xiàn)復(fù)制功能的示例代碼
本篇文章主要介紹了使用clipboard.js實現(xiàn)復(fù)制功能的示例代碼,詳細介紹了clipboard.js插件的使用,有興趣的可以了解一下2017-10-10第四篇Bootstrap網(wǎng)格系統(tǒng)偏移列和嵌套列
這篇文章主要介紹了Bootstrap網(wǎng)格系統(tǒng)偏移列和嵌套列的相關(guān)資料,非常不錯具有參考借鑒價值,需要的朋友可以參考下2016-06-06JS統(tǒng)計Flash被網(wǎng)友點擊過的代碼
JS統(tǒng)計Flash被網(wǎng)友點擊過的代碼...2007-05-05