TypeScript 中的 Any、Unknown、Never 和Void
大家好,我是前端西瓜哥。今天來(lái)學(xué)習(xí) TS 中幾個(gè)比較特殊的類型:any、never、never、void。
any
any 表示 任意類型。
它是任意類型的父類,任意類型的值都可以賦予給 any 類型:
它可以表示任何類型,并使用它們的語(yǔ)法,就像寫(xiě)沒(méi)有類型的原生 JS 一樣。
any 相當(dāng)于拋棄了類型系統(tǒng),會(huì)讓代碼變得不可預(yù)測(cè)和難以維護(hù),需要程序員小心維護(hù),一有不慎會(huì)造成運(yùn)行時(shí)的錯(cuò)誤,所以盡量少用。
但在引入一些沒(méi)有提供類型的第三方純 JS 庫(kù)時(shí),還是得將它們標(biāo)為 any,這個(gè)確實(shí)沒(méi)啥辦法。
除非你自己給第三方庫(kù)寫(xiě)類型聲明,但太不現(xiàn)實(shí),因?yàn)槟悴皇煜さ谌綆?kù)的 API,且可能有很復(fù)雜的類型推導(dǎo)要實(shí)現(xiàn)。
any 的存在是為了兼容無(wú)類型的 JS。TS 作為 JS 的超集,用 any 開(kāi)后門(mén)是不得不做的事情。
unknown
unknown 可以認(rèn)為是 類型更安全的 any。
和 any 一樣,unknown 也是任何類型的子類型,所有類型都可以傳給 unknown,包括 any。
說(shuō) unknown 更安全,是因?yàn)?nbsp;unknown 是不能進(jìn)行任何操作的。如果要使用,需要用 as 來(lái)進(jìn)行顯式的類型斷言。
或者我們可以用類型收窄(Type Narrowing);
對(duì)于一些可疑的沒(méi)有類型的變量,如果你不希望它被不小心使用,此時(shí)就可以用 unknown。
總結(jié)就是:unknown 能看不能用,想用先類型斷言。
never
never 表示一個(gè) 無(wú)法被觀測(cè)的類型,被賦予了該類型的變量什么都不能做。
使用 never 的一些場(chǎng)景。
(1)一個(gè)無(wú)法走到 return 返回值的函數(shù),比如一定會(huì)拋出錯(cuò)誤或死循環(huán):
(2)TS 在判斷條件下會(huì)做類型的收窄,當(dāng)類型收縮到無(wú)類型可用,類型就變成了 never:
或者做了一種不可能為 true 的類型收窄:
或無(wú)法求出交集的交叉類型:
(3)類型編程中,在做模式匹配時(shí),如果匹配失敗,還是要返回一個(gè)類型的。為了表示失敗,返回一個(gè) never 表示返回的類型是無(wú)法被使用的。
比如 TS 內(nèi)置的 Parameters 高級(jí)類型,會(huì)通過(guò)模式匹配提取函數(shù)的參數(shù)數(shù)組類型。如果無(wú)法匹配到參數(shù),會(huì)返回 never:
(4)類型編程中,將一些類型丟棄。never 在聯(lián)合類型以及重映射的 key 中會(huì)被丟棄。
比如 TS 內(nèi)置的 Exclude 高級(jí)類型,會(huì)將聯(lián)合類型 T 中的不屬于 U 的 key 丟棄掉。
void
void 用于表示一個(gè) 函數(shù)沒(méi)有返回值。
當(dāng)然在實(shí)際 JS 運(yùn)行時(shí),還是會(huì)返回一個(gè)默認(rèn)的 undefined 的。但 TS 給返回值設(shè)置為 void,語(yǔ)義更好些。
總結(jié)
any 是任意類型,具有所有類型的行為,可被執(zhí)行,可訪問(wèn)屬性,超脫于類型系統(tǒng)之外。
unknown 則是類型更安全的 any,同樣可以將任何類型賦給它,但不能執(zhí)行任何操作,必須用類型斷言來(lái)顯示說(shuō)明類型才能去執(zhí)行操作。
never 是無(wú)法觀測(cè)的類型,比如不會(huì)執(zhí)行完的函數(shù)的返回值,合并結(jié)果不存在的交叉類型。在類型編程中非常活躍,常用于丟棄一些子類型。
void 就比較簡(jiǎn)單,只是代表函數(shù)沒(méi)有返回值,沒(méi)有其他的場(chǎng)景了。