成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

這幾個 TypeScript 類型,90% 的人說不出原因

開發 前端
條件類型當 checkType(左邊的類型)是類型參數的時候,會有 distributive 的性質,也就是傳入聯合類型時會把每個類型單獨傳入做計算,最后把結果合并返回。

有這樣幾個 TypeScript 類型,大家先試著猜下 res 都是啥:

第一個:

傳入的類型參數為聯合類型 1 | 'a',問 res 是啥

type Test<T> = T extends number ? 1 : 2;

type res = Test<1 | 'a'>;

第二個:

傳入的類型參數為 boolean,問 res 是啥

type Test<T> = T extends true ? 1 : 2;

type res = Test<boolean>;

第三個:

傳入的類型參數為 any,問 res 是啥

type Test<T> = T extends true ? 1 : 2;

type res = Test<boolean>;

第四個:

傳入的類型參數為 never,問 res 是啥

type Test<T> = T extends true ? 1 : 2;

type res = Test<never>;

先記一下自己的答案,接下來我公布正確答案,大家看下猜對了幾個。

答案公布

第一個類型 res 是 1 | 2

再來看第二個類型,res 也是 1 | 2

接下來是第三個類型,res 也是 1 | 2

最后是第四個類型,res 是 never

不管答對了幾個都沒關系,關鍵是要知道它的原因,接下來我解釋下:

原因解釋

第一個類型 res 是 1 | 2

有同學可能會說,這里傳入的是聯合類型呀,也不是 number,為啥結果是這樣呢?

因為當條件類型的左邊是類型參數時,會有 distributive 的性質,也就是把聯合類型的每個類型單獨傳入求值,把每個的結果合并成聯合類型,這叫做分布式條件類型。

這里的 T extends number 的左邊是類型參數 T,傳入的是聯合類型 1 | 'a',所以會把 1 傳入求值、把 2 傳入求值,最后把結果合并成聯合類型,也就是 1 | 2。

再來看第二個類型,res 也是 1 | 2

為啥這里也是 1 | 2 呢, 剛才說的分布式條件類型是針對聯合類型的呀?

沒錯,boolean 其實也是聯合類型,所以會把 true 和 false 分別傳入求值,最后結果合并成聯合類型,所以是 1 | 2。

接下來是第三個類型,res 也是 1 | 2

同學可能會說:哦,我知道了,any 也是聯合類型。

錯,any 不是聯合類型,這里是因為條件類型對 any 做了特殊處理,如果左邊是 any,那么直接把 trueType 和 falseType 合并成聯合類型返回。

最后是第四個類型,res 是 never

咋還出來個 never,不是只有 1 和 2 么?

這里確實也是 TS 的特殊處理,當條件類型左邊是 never 時,直接返回 never。

你說了這么多,我怎么知道是不是真的呢,萬一是你編的呢?

有懷疑很正常,這也是應該有的態度,不過這些確實都是真的,接下來我從源碼來驗證下。

從 TS 源碼解釋原因

這里的重點不在如何讀 TypeScript 源碼上,我就略過過程了,直接給結果。

對如何閱讀 TypeScript 源碼感興趣的同學,可以看我之前的一篇文章:《我讀 TypeScript 源碼的秘訣都在這里了》,或者看我剛上線的掘金小冊《TypeScript 類型體操通關秘籍》,小冊里會帶大家從源碼解釋各種類型的原理。

先來解釋第一個聯合類型 + 條件類型的情況:

type Test<T> = T extends number ? 1 : 2;

type res = Test<1 | 'a'>;

TypeScript 在處理到條件類型 Conditional Type 的時候,會設置一個 isDistributive 的屬性,根據類型參數是不是 checkType(左邊的類型)來設置。

因為 T extends number 的 checkType 是 T,所以這里的 isDistributive 就是 true,也就是它是分布式條件類型。

那么是分布式條件類型會做什么處理呢?

會在求值的時候把每個類型單獨傳入求值,最后把結果合并。

對應的源碼是這樣的:

這里都不用解釋了,注釋都寫的很清楚了, T extends U ? X : Y 當傳入的 T 是 A | B 時,結果是 (A extends U ? X : Y)|(B extends U ? X : Y)。

這就是分布式條件類型遇到聯合類型時的處理。

所以,源碼走到了 mapTypeWithAlias 這個分支,就是做每個類型單獨傳入求值的。

我們從源碼驗證了分布式條件類型的特性!

接下來再來看第二個類型,當條件類型 + boolean 時:

type Test<T> = T extends true ? 1 : 2;

type res = Test<boolean>;

前面說 boolean 也是聯合類型,這是不是真的呢?

debug 發現它也走到這個分支了。說明條件成立,boolean 是 union 或者 never

驗證一下:

這里的 flags 就是每一個位表示一種類型,然后通過位運算的按位與來判斷是否是那種類型:

這種方式占用空間小,計算速度快,很多框架都是這樣來標識類型的,比如 React。

所以,從結果來看 boolean 是聯合類型,也就是 true | false。那自然也會觸發分布式條件類型的特性,把 true 和 false 單獨傳入求值,最后把結果合并。

然后是第三個類型,當條件類型 + any 時:

type Test<T> = T extends true ? 1 : 2;

type res = Test<any>;

debug 會發現并沒有走到 mapType 那個分支,而走了另一個分支:

這就說明條件不滿足,any 不是聯合類型呀,我們也可以通過 flags 看下:

按位與的結果是 0,也說明了它不是 union 和 never。

那為啥結果還是 1 | 2 呢?

繼續往下走,看條件類型的求值邏輯,會發現這樣一段代碼:

注釋是 Return union of trueType and falseType for 'any' since it matches anything,意思是是返回 trueType 和 falseType 的聯合類型,因為 any 匹配任何類型。

原因不就出來了么。(不得不說,TS 源碼的注釋寫的真不錯)

然后就是最后一個類型,當條件類型 + never 時:

type Test<T> = T extends true ? 1 : 2;

type res = Test<never>;

為啥直接返回了 never 呢?

debug 會發現 never 也走到 mapType 這個分支了:

啥情況,never 又不是聯合類型,咋分呀。

人家條件里確實寫的是 Union 或者 Never:

說明肯定對 Never 做了特殊處理,別著急,我們繼續往下看。

繼續往下走會發現 Union 和 Never 在這里分叉了:

然后 mapType 里對 never 類型直接就給返回了該類型,也就是 never:

這就是為啥結果既不是 trueType、也不是 falseType,而是 never。

至此,我們通過源碼來驗證了上面說的原因的真實性。

總結

TypeScript 的類型系統有一些特殊的設計:

條件類型當 checkType(左邊的類型)是類型參數的時候,會有 distributive 的性質,也就是傳入聯合類型時會把每個類型單獨傳入做計算,最后把結果合并返回。這叫做分布式條件類型。

此外,條件類型遇到 never 會直接返回 never,遇到 any 會返回 trueType 和 falseType 的聯合類型。

再就是 boolean 也是聯合類型,是 true | false。

類似這種特殊的地方還是不少的,這些我都總結在了 《TypeScript 類型體操通關秘籍》的小冊里,會全面系統的講 TypeScript 類型編程,還有會教大家如何 TypeScript 源碼來解釋這些類型的原理。感興趣的可以看一下,保證不坑。而且現在買很便宜的,只有 17 塊。

責任編輯:姜華 來源: 神光的編程秘籍
相關推薦

2025-03-24 10:11:06

SpringJava開發

2019-10-30 09:02:04

JavaCPU 線程

2020-08-31 10:21:41

5G波束天線

2021-06-11 13:59:22

CSS原子類

2020-02-03 09:29:32

JavaScript代碼斷點

2021-10-27 10:07:59

GitHub代碼開發者

2019-02-28 20:20:43

Python技巧編程語言

2020-04-20 14:50:02

前端技巧優化

2023-11-30 08:19:52

偽類CSS

2020-09-18 06:48:21

Python編程語言

2022-05-20 15:27:41

React工具Vue

2024-07-01 08:31:14

Spring工具類代碼

2020-08-24 13:15:59

Python代碼描述符

2020-08-24 15:25:27

Python 開發運維

2018-11-21 08:12:19

人工智能失業機器

2025-05-23 08:00:00

VLAN虛擬局域網網絡

2020-07-24 08:51:54

Java編程語言開發

2022-02-21 16:16:24

災難恢復解決方案備份

2022-04-12 08:43:21

Python內置模塊

2018-04-18 06:56:26

iPhone手機電量
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品欧美一区二区精品久久久 | 国产精品色综合 | 国产一区二区三区免费 | 在线免费国产 | 伊人网综合在线观看 | 狠狠色综合久久丁香婷婷 | 亚洲在线一区 | 亚洲欧美日韩国产综合 | 人成久久 | 一级做a毛片 | 久久福利电影 | 免费在线精品视频 | 国产成人在线一区 | www.色午夜.com | 久久久久久国产精品久久 | 最新免费av网站 | 天天影视网天天综合色在线播放 | 九九精品网| 91久久国产精品 | 国产区在线观看 | 亚洲国产精品久久 | 91精品国产综合久久久久久丝袜 | 91.com在线观看 | 成人精品一区二区户外勾搭野战 | 国户精品久久久久久久久久久不卡 | 91精品成人久久 | 中文字幕一区二区三区四区 | 日本一道本视频 | 18成人在线观看 | 日韩福利| 高清视频一区二区三区 | 五月婷婷 六月丁香 | 国产精品久久久久久久久久久久 | 日韩中文一区 | 在线一区视频 | 亚洲一级av毛片 | 日韩色图在线观看 | 日韩精品一区二区三区中文字幕 | 久久精彩视频 | 色播久久 | 黄色免费网站在线看 |