TypeScript中的never類型你了解嗎
1. never 類型的理解
TypeScript 中的 never 類型,表示:永遠(yuǎn)不會(huì)發(fā)生的值的類型。
換句話說,就是不可能存在的類型,即沒有值的類型。
2. 可能會(huì)出現(xiàn) never 類型的一些情況
2.1. 函數(shù)拋出異常
如果一個(gè)函數(shù)拋出異常,那么它的返回類型就是 never。因?yàn)樵诤瘮?shù)拋出異常后,會(huì)直接中斷程序的運(yùn)行,這使得程序不會(huì)繼續(xù)執(zhí)行到函數(shù)的返回語句那一步。
上面的例子中,函數(shù) throwError 拋出異常,鼠標(biāo)移到 throwError 函數(shù)上面,可以看到函數(shù)的返回值類型為 never。
2.2. 不會(huì)有返回值的函數(shù)
如果一個(gè)循環(huán)永遠(yuǎn)無法正常結(jié)束,比如無限循環(huán)或者總是拋出異常,那么該循環(huán)的類型被推斷為 never。
上面的例子中,函數(shù) infiniteLoop 是一個(gè)無限循環(huán)函數(shù),沒有任何的終止循環(huán)的語句,函數(shù)執(zhí)行永遠(yuǎn)不會(huì)結(jié)束,因此不會(huì)有任何的返回值,鼠標(biāo)移到 infiniteLoop 函數(shù)上面,可以看到函數(shù)的返回值類型為 never。
2.3. 類型判斷或類型縮小的細(xì)化(全面性檢查)
在條件語句中,如果 TypeScript 能夠推斷出某個(gè)分支永遠(yuǎn)不會(huì)執(zhí)行,那么該分支的類型會(huì)被推斷為 never 。
type Value = number | string; const processValue = (value: Value) => { if (typeof value === "number") { // 在這個(gè)分支中,value 的類型被細(xì)化為 number } else if (typeof value === "string") { // 在這個(gè)分支中,value 的類型被細(xì)化為 string } else { // 在這個(gè)分支中,value 的類型被細(xì)化為 never,因?yàn)?value 不可能同時(shí)為 string 和 number const n: never = value } }
上面的例子中,else 分支里面,value 的類型將被細(xì)化為 never 類型,然后我們將 value 賦值給一個(gè)顯示聲明了 never 類型的變量,如果邏輯正確,上面的代碼可以正常編譯通過,但如果你把 Value 的類型改成 number | string | boolean 的聯(lián)合類型,此時(shí) else 分支的 value 類型就會(huì)被細(xì)化成 boolean 類型,此時(shí)把 value 賦值給一個(gè)顯示聲明了 never 類型的變量就會(huì)報(bào)錯(cuò)。
type Value = number | string | boolean; const processValue = (value: Value) => { if (typeof value === "number") { // 在這個(gè)分支中,value 的類型被細(xì)化為 number } else if (typeof value === "string") { // 在這個(gè)分支中,value 的類型被細(xì)化為 string } else { // 在這個(gè)分支中,value 的類型被細(xì)化為 boolean 類型,因?yàn)?value 不可能同時(shí)為 string 和 number // 此時(shí),把 value 賦值給一個(gè)顯示聲明了 never 類型的變量 n 就會(huì)報(bào)錯(cuò)。 // 下面的賦值語句會(huì)報(bào)錯(cuò):不能將類型“boolean”分配給類型“never”。 const n: never = value } }
3. never 類型的特點(diǎn)
3.1. never 類型會(huì)從聯(lián)合類型中移除
任意類型和 never 類型的聯(lián)合類型都是其本身,就好比如:任意數(shù)字和0相加,都等于該數(shù)字。
type T1 = number | never; // number type T2 = string | never; // string type T3 = boolean | never; // boolean type T4 = any | never; // any type T5 = unknown | never; // unknown type T6 = never | never; // never type T7 = "abc" | never; // "abc" type T8 = 123 | never; // 123
利用這個(gè)特點(diǎn),我們可以做很多事情,比如:篩選。
我們可以利用條件類型把不符合類型 Type 的類型先轉(zhuǎn)換成 never 類型,然后利用聯(lián)合類型把 never 類型過濾掉,得到我們想要的結(jié)果。
type Filter<T, U> = T extends U ? T : never type RESULT = Filter<"Echo" | 26 | true | "GuangZhou", string>
上面的代碼,按照分布式條件類型機(jī)制,Filter<"Echo" | 26 | true | "GuangZhou", string>
將被分解成如下代碼:
type RESULT = | ("Echo" extends string ? "Echo" : never) | (26 extends string ? 26 : never) | (true extends string ? true : never) | ("GuangZhou" extends string ? "GuangZhou" : never)
進(jìn)一步被解析,得到如下代碼:
type RESULT = "Echo" | never | never | "GuangZhou"
再一步解析,得到結(jié)果:
type RESULT = "Echo" | "GuangZhou"
3.2. never 類型與任意類型的交叉類型都是 never
type T1 = number & never; // never type T2 = string & never; // never type T3 = boolean & never; // never type T4 = any & never; // never type T5 = unknown & never; // never type T6 = never & never; // never type T7 = "abc" & never; // never type T8 = 123 & never; // never
3.3. never 可以賦值給任意類型
由于 never 類型是所有其他類型的子類型,所以可以將 never 賦值給任何其他類型。
let n: never let str: string = n let num: number = n let b: boolean = n let any: any = n let unknown: unknown = n let func: () => void = n let symbol: symbol = n let n1: never = n
3.4. 其他類型不能賦值給 never
由于 never 沒有子類型,所以除了 never 本身,任何類型都不能賦值給 never 類型。
let n: never n = "Echo" // 報(bào)錯(cuò):不能將類型“string”分配給類型“never” n = 26 // 報(bào)錯(cuò):不能將類型“number”分配給類型“never” n = true // 報(bào)錯(cuò):不能將類型“boolean”分配給類型“never” n = [1, 2, 3] // 報(bào)錯(cuò):不能將類型“number[]”分配給類型“never” n = Symbol() // 報(bào)錯(cuò):不能將類型“symbol”分配給類型“never” n = {} // 報(bào)錯(cuò):不能將類型“{}”分配給類型“never” n = new Array() // 報(bào)錯(cuò):不能將類型“any[]”分配給類型“never” n = (...arg: any) => {} // 報(bào)錯(cuò):不能將類型“(...arg: any) => void”分配給類型“never”
4. 總結(jié)
以上就是我對(duì) TypeScript 中 never
類型的理解,如果有不正確的地方,歡迎大家在評(píng)論區(qū)多多指正!
到此這篇關(guān)于TypeScript中的never類型你了解嗎的文章就介紹到這了,更多相關(guān)TypeScript never類型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js中substring和substr兩者區(qū)別和使用方法
這篇文章主要介紹了js中substring和substr兩者區(qū)別和使用方法,每一個(gè)步驟都有相應(yīng)的文字介紹,感興趣的小伙伴們可以參考一下2015-11-11open 動(dòng)態(tài)修改img的onclick事件示例代碼
動(dòng)態(tài)修改img的onclick事件,使用open也可輕松做到,下面有個(gè)不錯(cuò)的示例,需要的朋友可以參考下2013-11-11JavaScript實(shí)現(xiàn)背景圖像切換3D動(dòng)畫效果示例詳解
這篇文章主要為大家介紹了JavaScript實(shí)現(xiàn)背景圖像切換3D動(dòng)畫效果示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09JavaScript中運(yùn)算符與數(shù)組擴(kuò)展詳細(xì)講解
這篇文章主要介紹了JavaScript中運(yùn)算符與數(shù)組擴(kuò)展方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-11-11JS實(shí)現(xiàn)帶有3D立體感的銀灰色豎排折疊菜單代碼
這篇文章主要介紹了JS實(shí)現(xiàn)帶有3D立體感的銀灰色豎排折疊菜單代碼,可實(shí)現(xiàn)基本的JS響應(yīng)鼠標(biāo)事件動(dòng)態(tài)展開與折疊菜單欄的功能,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-10-10微信小程序-圖片、錄音、音頻播放、音樂播放、視頻、文件代碼實(shí)例
本篇文章主要介紹了微信小程序-圖片、錄音、音頻播放、音樂播放、視屏、文件代碼實(shí)例,有興趣的可以了解一下。2016-11-11JS操作對(duì)象數(shù)組實(shí)現(xiàn)增刪改查實(shí)例代碼
JS提供了很多方便操作數(shù)組的方法,這篇文章主要給大家介紹了關(guān)于JS操作對(duì)象數(shù)組實(shí)現(xiàn)增刪改查的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2021-07-07