TypeScript類(lèi)型體操--Merge邓馒、Diff、Flip

大家好蛾坯,我蘇先生光酣,一名熱愛(ài)鉆研、樂(lè)于分享的前端切圖仔

github與好文

前言

上一節(jié)倘零,我們通過(guò)12個(gè)內(nèi)置工具類(lèi)型初步感受了下類(lèi)型體操是個(gè)啥:通過(guò)對(duì)一個(gè)已知類(lèi)型編程生成一個(gè)新的類(lèi)型

按照本小冊(cè)的規(guī)劃唱遭,還差87個(gè)...

本節(jié),我們?cè)黾酉码y度呈驶,一起來(lái)實(shí)現(xiàn)下Merge拷泽、Diff、Flip

提示

對(duì)于語(yǔ)法層面的知識(shí)點(diǎn)本系列(類(lèi)型體操開(kāi)頭的標(biāo)題)不會(huì)展開(kāi)說(shuō)明哈袖瞻,可以自行搜索學(xué)習(xí)其他大佬的優(yōu)質(zhì)文章或者等我后續(xù)更新補(bǔ)充

Merge

功能

合并兩個(gè)已知類(lèi)型司致,對(duì)于同名的key,向前進(jìn)行覆蓋聋迎,最后返回一個(gè)新類(lèi)型

實(shí)現(xiàn)

它接收兩個(gè)泛型參數(shù):T脂矫、U

type Merge<T,U>

我們要判斷的是key是否重復(fù),因此我們必須拿到每一個(gè)key值霉晕,這在TypeScript中可以通過(guò)keyof來(lái)獲取庭再,并且它返回的是一個(gè)聯(lián)合類(lèi)型

type KOfT = keyof T
type KOfU = keyof U

然后,我們需要將KOfT和KOfU進(jìn)行合并牺堰,生成一個(gè)具有不重復(fù)key的聯(lián)合類(lèi)型

type UniKey = KOfT | KOfU

我們使用|生成一個(gè)新的聯(lián)合類(lèi)型拄轻,在這一過(guò)程中,TypeScript會(huì)自動(dòng)將重名的key進(jìn)行剔除伟葫,如圖所示

image.png

接著哺眯,我們需要拿到T中的每一個(gè)key到U中判斷是否存在,因此我們還需要使用in關(guān)鍵字進(jìn)行遍歷

type UniKey = K in KOfT | KOfU

然后扒俯,我們使用extends關(guān)鍵字來(lái)構(gòu)建條件類(lèi)型奶卓,并分情況討論:

1-K是KOfU的子類(lèi)型,則直接使用KOfU的key作為合并后的結(jié)果

2-如果不是撼玄,則判斷是否是KOfT的子類(lèi)型夺姑,不是則使用never進(jìn)行過(guò)濾

K extends KOfU ? S[K] : K extends KOfT ? T[K] : never

最后我們只需要借助映射類(lèi)型進(jìn)行下組裝就可以啦:

type Merge<T, U> = {
  [K in keyof T | keyof U]: K extends keyof U
    ? U[K]
    : K extends keyof T
    ? T[K]
    : never;
};

Diff

功能

找出兩個(gè)對(duì)象類(lèi)型的差異,并將差異部分組成一個(gè)新的類(lèi)型返回

實(shí)現(xiàn)

它接收兩個(gè)泛型參數(shù)

type Diff<T,U>

這兩個(gè)泛形應(yīng)該是對(duì)象類(lèi)型掌猛,因此我們需要對(duì)其進(jìn)行約束

type Diff<T extends object,U extends object>

同樣的盏浙,我們要先將獲取到兩個(gè)類(lèi)型的所有的key眉睹,然后才能考慮進(jìn)行比較判斷,關(guān)于key的獲取废膘,按照前文的實(shí)現(xiàn)竹海,我們可以使用keyof先將其轉(zhuǎn)換為聯(lián)合類(lèi)型再通過(guò)|來(lái)得到,但是這里我們換一種實(shí)現(xiàn)方式丐黄,我們先對(duì)接口進(jìn)行合并然后再keyof取值

type UniKey = keyof (T&U)

接著我們拿到新類(lèi)型UniKey中的每一個(gè)key斋配,即K

K in UniKey

此時(shí),如果我們能拿到兩個(gè)類(lèi)型共有的部分灌闺,那就可以使用在手寫(xiě)12個(gè)TypeScript內(nèi)置工具類(lèi)型中實(shí)現(xiàn)的Exclude工具類(lèi)型進(jìn)行排除:

1-獲取類(lèi)型的公共部分

type Com = keyof (T|U)

2-使用Exclude工具類(lèi)型將key排除

type Excluded = Exclude<K,Com>

接著我們將其斷言為新的類(lèi)型Excluded

K in UniKey as Excluded

至于key對(duì)應(yīng)的原泛型中的類(lèi)型艰争,我們使用索引訪問(wèn)類(lèi)型直接從接口合并結(jié)果中取就好了

(T&U)[K]

最后,老規(guī)矩桂对,我們通過(guò)映射類(lèi)型進(jìn)行下組裝:

type Diff<T extends object,U extends object> = {
    [K in keyof (T & U) as Exclude<K,keyof (T|U)>]:(T&U)[K]
}

推廣時(shí)間:

我本來(lái)一直在推我的約定式路由庫(kù)甩卓,不過(guò)目前看來(lái)收效甚微。所以我這里就不再花大篇幅去寫(xiě)了蕉斜,就簡(jiǎn)單提一嘴


Flip

功能

交換一個(gè)對(duì)象類(lèi)型的key和value逾柿,并返回一個(gè)新的類(lèi)型

實(shí)現(xiàn)

它接受一個(gè)泛型類(lèi)型T

type Flip<T>

由于對(duì)象類(lèi)型的key只能是基本類(lèi)型,但是其value卻可以是任意類(lèi)型宅此,那就意味著鹿寻,當(dāng)我們使用索引類(lèi)型T[K]來(lái)取value作為新的key時(shí),將會(huì)有報(bào)錯(cuò)風(fēng)險(xiǎn)诽凌,因此,我們對(duì)key進(jìn)行下約束

type Flip<T extends Record<string|number|boolean,any>>

接著我們獲取到每一個(gè)key

K in keyof T

然后對(duì)其進(jìn)行斷言

type NewKey = K as T[K]

最后使用映射進(jìn)行組裝坦敌,并將K作為value即可

type Flip<T extends Record<string|number|boolean,any>> = {
    [K in keyof T K as T[K]] : K
}

關(guān)于“理想很豐滿(mǎn)侣诵,現(xiàn)實(shí)很骨感”這句話(huà),許是對(duì)的S健6潘场!上文的寫(xiě)法會(huì)被TypeScript推斷出錯(cuò)誤

[圖片上傳失敗...(image-c94871-1686489361019)]

按照錯(cuò)誤提示蘸炸,我們將boolean修改為symbol后的最終代碼實(shí)現(xiàn)如下

type Flip<T extends Record<string|number|symbol,any>> = {
    [K in keyof T as T[K]] : K
}

如果本文對(duì)您有用躬络,希望能得到您的點(diǎn)贊和收藏

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市搭儒,隨后出現(xiàn)的幾起案子穷当,更是在濱河造成了極大的恐慌,老刑警劉巖淹禾,帶你破解...
    沈念sama閱讀 222,252評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件馁菜,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡铃岔,警方通過(guò)查閱死者的電腦和手機(jī)汪疮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人智嚷,你說(shuō)我怎么就攤上這事卖丸。” “怎么了盏道?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,814評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵稍浆,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我摇天,道長(zhǎng)粹湃,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,869評(píng)論 1 299
  • 正文 為了忘掉前任泉坐,我火速辦了婚禮为鳄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘腕让。我一直安慰自己孤钦,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布纯丸。 她就那樣靜靜地躺著偏形,像睡著了一般。 火紅的嫁衣襯著肌膚如雪觉鼻。 梳的紋絲不亂的頭發(fā)上俊扭,一...
    開(kāi)封第一講書(shū)人閱讀 52,475評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音坠陈,去河邊找鬼萨惑。 笑死,一個(gè)胖子當(dāng)著我的面吹牛仇矾,可吹牛的內(nèi)容都是我干的庸蔼。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼贮匕,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼姐仅!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起刻盐,我...
    開(kāi)封第一講書(shū)人閱讀 39,924評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤掏膏,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后敦锌,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體壤追,經(jīng)...
    沈念sama閱讀 46,469評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評(píng)論 3 342
  • 正文 我和宋清朗相戀三年供屉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了行冰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片溺蕉。...
    茶點(diǎn)故事閱讀 40,680評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖悼做,靈堂內(nèi)的尸體忽然破棺而出疯特,到底是詐尸還是另有隱情,我是刑警寧澤肛走,帶...
    沈念sama閱讀 36,362評(píng)論 5 351
  • 正文 年R本政府宣布漓雅,位于F島的核電站,受9級(jí)特大地震影響朽色,放射性物質(zhì)發(fā)生泄漏邻吞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評(píng)論 3 335
  • 文/蒙蒙 一葫男、第九天 我趴在偏房一處隱蔽的房頂上張望抱冷。 院中可真熱鬧,春花似錦梢褐、人聲如沸旺遮。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,519評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)耿眉。三九已至,卻和暖如春鱼响,著一層夾襖步出監(jiān)牢的瞬間鸣剪,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,621評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工丈积, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留筐骇,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,099評(píng)論 3 378
  • 正文 我出身青樓桶癣,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親娘锁。 傳聞我的和親對(duì)象是個(gè)殘疾皇子牙寞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容