新聞中心
重載是指一個函數(shù)可以有不同的參數(shù)和返回值,也就是有不同的函數(shù)簽名。

創(chuàng)新互聯(lián)建站成立與2013年,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項目成都網(wǎng)站設(shè)計、成都做網(wǎng)站網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元中陽做網(wǎng)站,已為上家服務(wù),為中陽各地企業(yè)和個人服務(wù),聯(lián)系電話:18982081108
ts 支持函數(shù)重載,可以為同一個函數(shù)定義多個不同的類型:
重載的寫法一共有三種(估計大多數(shù)人只會一種):
declare function func(name: string): string;
declare function func(name: number): number;
這種大家比較常用,聲明兩個同名函數(shù),就能達到重載的目的:
函數(shù)可以用 interface 的方式聲明,同樣,也可以用 interface 的方式聲明函數(shù)重載:
函數(shù)類型可以取交叉類型,也就是多種類型都可以,其實也是函數(shù)重載的意思:
重載雖然是很有用的特性,但有的時候重載多了寫起來還是挺麻煩的。
比如 ts 提供的 lib.dom.ts 里就有這樣的類型定義:
因為每種參數(shù)對應(yīng)不同的返回值,所以它就重載了這么多。
這樣寫起來也太麻煩了吧,能不能用類型編程動態(tài)生成呢?
考慮下重載的三種寫法,declare 和 interface 不行,但是 & 可以呀,能不能我傳入一個聯(lián)合類型,然后它給返回交叉類型呢?
比如這樣:
都提示出來了肯定是可以的,我們看下砸實現(xiàn)的吧:
聯(lián)合轉(zhuǎn)交叉函數(shù)參數(shù)有逆變的性質(zhì),也就是類型縮小,比如參數(shù)能同時傳 A、B、C 的話,參數(shù)類型怎么定義?
肯定是 A、B、C 的交集呀,也就你 A & B & C 的交叉類型,這樣就可以接收 A、B、C 的參數(shù)了。
可以利用這個性質(zhì)實現(xiàn)聯(lián)合轉(zhuǎn)交叉。
比如這樣:
都提示出來了肯定是可以的,我們看下砸實現(xiàn)的吧:
聯(lián)合轉(zhuǎn)交叉
函數(shù)參數(shù)有逆變的性質(zhì),也就是類型縮小,比如參數(shù)能同時傳 A、B、C 的話,參數(shù)類型怎么定義?
肯定是 A、B、C 的交集呀,也就你 A & B & C 的交叉類型,這樣就可以接收 A、B、C 的參數(shù)了。
可以利用這個性質(zhì)實現(xiàn)聯(lián)合轉(zhuǎn)交叉。
type UnionToIntersection =
(U extends U ? (x: U) => unknown : never) extends (x: infer R) => unknown
? R
: never
測試一下:
這里的類型參數(shù) U 是傳入的聯(lián)合類型,加一個 U extends U 是為了觸發(fā)分布式條件類型的特性。
什么是分布式條件類型呢?
當類型參數(shù)為聯(lián)合類型,并且在條件類型左邊直接引用該類型參數(shù)的時候,TypeScript 會把每一個元素單獨傳入來做類型運算,最后再合并成聯(lián)合類型,這種語法叫做分布式條件類型。
比如這樣一個聯(lián)合類型:
type Union = 'a' | 'b' | 'c';
我們想把其中的 a 大寫,就可以這樣寫:
type UppercaseA- =
Item extends 'a' ? Uppercase- : Item;
回到聯(lián)合轉(zhuǎn)交叉的這個高級類型:
加一個 U extends U 或者 U extends any 就能觸發(fā)分布式條件類型的特性,讓聯(lián)合類型分成每一個類型單獨傳入做計算,最后把結(jié)果合并成聯(lián)合類型。
然后再把它放到函數(shù)參數(shù)的位置,構(gòu)造一個函數(shù)類型,通過模式匹配的方式提取參數(shù)的類型到 infer 聲明的局部變量 R 里返回。
這樣的結(jié)果就是交叉類型。
原因上面說過了,函數(shù)參數(shù)有逆變的性質(zhì),傳入聯(lián)合類型會返回交叉類型。
實現(xiàn)了聯(lián)合轉(zhuǎn)交叉之后,函數(shù)重載也就可以寫出來了:
比如三個重載的返回值分別是 Aaa、Bbb、Ccc:
我們想基于這個生成重載的類型定義,傳入聯(lián)合類型返回重載的函數(shù):
就可以這樣寫:
type UnionToOverloadFunction=
UnionToIntersection<
T extends any ? (type: T) => ReturnValueMap[T] : never
>;
類型參數(shù) T 是 ReturnValueMap 里的 key,約束為 keyof ReturnValueMap。
通過 T extends any 觸發(fā)聯(lián)合類型在分布式條件類型中的分發(fā)特性,讓 'aaa' 'bbb' 'ccc' 分別傳入做計算,返回構(gòu)造出的函數(shù)類型的聯(lián)合。
我們先單獨測試下這部分:
可以看到返回的是構(gòu)造出的函數(shù)類型的聯(lián)合類型。
然后就用上面的 UnionToIntersection 轉(zhuǎn)交叉就可以了:
這樣就實現(xiàn)了重載函數(shù)的動態(tài)生成:
對比下最開始那種寫法:
是不是清爽多了!而且還可以寫一些動態(tài)邏輯。
總結(jié)
ts 函數(shù)重載一共有三種寫法:declare function、interface、交叉類型 &。
當重載比較多的時候,直接列出來還是比較麻煩的,這時候可以用類型編程來動態(tài)生成函數(shù)重載。
我們實現(xiàn)了聯(lián)合轉(zhuǎn)交叉,利用了函數(shù)參數(shù)的逆變性質(zhì),也就是當參數(shù)可能是多個類型時,會返回它們的交叉類型。
然后又利用分布式條件類型的性質(zhì),當傳入聯(lián)合類型時,會把類型單獨傳入做計算,最后把結(jié)果合并成聯(lián)合類型。
利用這個實現(xiàn)了傳入聯(lián)合類型返回構(gòu)造出的函數(shù)的聯(lián)合類型,然后再結(jié)合聯(lián)合轉(zhuǎn)交叉就實現(xiàn)了函數(shù)重載的動態(tài)生成。
當你寫重載寫的太多的時候,不妨試一下用類型編程的方式動態(tài)生成吧!
分享文章:什么?函數(shù)類型重載還可以動態(tài)生成?
標題來源:http://m.fisionsoft.com.cn/article/dhpjjjg.html


咨詢
建站咨詢
