<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
這兩天東東遇到一個 TS 的問題,跑來問我。
問題是這樣的:
這樣一個 interface,想取出 userInfo 的型別來:
interface Result{ data?: { userInfo?: { name: string; } } }
他是這樣取的:
type userInfo = Result['data']['userInfo'];
但是會報錯:
說是 userInfo 不在這個聯合型別上。
這很正常,因為可選索引的含義就是值和 undefined 的聯合型別 value | undefined。
於是他問我應該怎麼取?
我和他說這個問題有兩種不同複雜度的解決方案,有簡單的有複雜的,問他想聽哪個。
他說想聽簡單的,於是我告訴他這樣寫:
type userInfo = Required<Required<Result>['data']>['userInfo']
Required 是 ts 內建的高階型別,是把索引型別的所有可選修飾去掉的。
所以每一層用 Required 處理一下再取索引的值就可以了。
但是這樣雖然簡單,當取的層數多了要寫很多次 Required,也挺麻煩的。
然後東東又問我如果是複雜的那個,要怎麼寫?
我和他說複雜的那個寫起來麻煩一些,但好處是用起來簡單,不管多少層都只需要處理一次:
首先要知道 Required 是怎麼實現的:
他這裡用到了對映型別的語法,作用是對索引型別做一些修改,生成新的索引型別。
P in keyof T 就是遍歷索引型別 T 中的所有索引 P,用來構造新的索引型別,值保持不變,也就是 T[P]。
構造的過程中可以加上可選的修飾、也可以去掉可選的修飾,還可以對值和索引做一些修改。
所以和 Required 相對的 Partial 就是這樣實現的:
我們想一次處理完所有層級,都把可選的修飾給去掉,那就要遞迴處理,也就是這樣:
type DeepRequired<Obj> = { [Key in keyof Obj]-?: IsOptional<Key, Obj> extends never? Obj[Key]: DeepRequired<Obj[Key]> }
遍歷索引型別 Obj 中的所有索引 Key,通過 -? 去掉可選,然後對值要做一下判斷,如果還是可選索引,那就遞迴處理。
那怎麼實現這個 IsOptional 的判斷索引是否是可選的高階型別呢?
判斷某個型別要根據他的性質來,可選的性質就是 value | undefined,也就是說可能是空。
可以這樣來實現可選的判斷:
type IsOptional<Key extends keyof Obj, Obj> = {} extends Pick<Obj, Key> ? Key : never;
Obj 是索引型別,Key 是他的某個索引,因為可選索引的性質是可能為空,所以 {} 就可能是索引型別的子型別。
這裡的 Pick 也是內建的高階型別,作用是取出一部分索引構造新的索引型別:
同樣是通過對映型別的語法實現的:
這裡 a 可能是沒有的,那當沒有的時候不就是 {} 麼? 所以可以用 {} extends Pick<Obj, Key> 來判斷是不是可選索引。
綜上,遞回去掉索引型別的可選修飾就是這樣實現的:
type IsOptional<Key extends keyof Obj, Obj> = {} extends Pick<Obj, Key> ? Key : never; type DeepRequired<Obj> = { [Key in keyof Obj]-?: IsOptional<Key, Obj> extends never? Obj[Key]: DeepRequired<Obj[Key]> }
我們測試一下:
現在只要處理一次,就可以取任意層級的索引值了,方便了很多。
其實寫成這樣就可以用了,但是有時候你會遇到這樣的問題:
TS 沒有把最終的結果計算出來。
這個是 TS 的機制,預設是懶計算的,用不到的不會計算。
那怎麼讓他計算出最終結果呢?
加上一段邏輯觸發計算就可以了,比如 xxx extends any 這種肯定會成立的條件判斷:
再測試一下你就會發現 TS 計算出了最終的結果:
想取一個可選索引的值,需要先用 Required 把索引型別去掉可選然後再取。但是當層數多了的話,這樣一層層處理挺麻煩的,可以用型別程式設計遞迴處理下。
用對映型別的語法去掉索引型別的可選修飾,判斷值的型別,如果還是可選的索引,那就繼續遞迴的處理。
判斷可選索引是通過可選的性質來的,可選索引的值是 value | undefined, 所以 {} extends Pick<Obj, Key> 成立的話就代表這個 Key 是可選的。
可能會遇到型別沒有全部計算的問題,這是 TS 的機制,預設是懶計算的,可以加上 xx extends any 這種不影響結果的條件型別來觸發計算。
層層用 Required 處理在層數少的情況下比較簡單,但層數多了的時候還是遞迴處理更方便一些,而且這樣的高階型別是可以複用的,可以用在別的地方,這也是型別程式設計的好處。
到此這篇關於TypeScript 型別程式設計之索引型別遞回去掉可選修飾的文章就介紹到這了,更多相關TypeScript 索引型別遞迴內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45