自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

什么?函數類型重載還可以動態(tài)生成?

開發(fā) 前端
ts 函數重載一共有三種寫法:declare function、interface、交叉類型 &。當重載比較多的時候,直接列出來還是比較麻煩的,這時候可以用類型編程來動態(tài)生成函數重載。

重載是指一個函數可以有不同的參數和返回值,也就是有不同的函數簽名。

ts 支持函數重載,可以為同一個函數定義多個不同的類型:

重載的寫法一共有三種(估計大多數人只會一種):

declare function func(name: string): string;
declare function func(name: number): number;

這種大家比較常用,聲明兩個同名函數,就能達到重載的目的:

函數可以用 interface 的方式聲明,同樣,也可以用 interface 的方式聲明函數重載:

函數類型可以取交叉類型,也就是多種類型都可以,其實也是函數重載的意思:

重載雖然是很有用的特性,但有的時候重載多了寫起來還是挺麻煩的。

比如 ts 提供的 lib.dom.ts 里就有這樣的類型定義:

因為每種參數對應不同的返回值,所以它就重載了這么多。

這樣寫起來也太麻煩了吧,能不能用類型編程動態(tài)生成呢?

考慮下重載的三種寫法,declare 和 interface 不行,但是 & 可以呀,能不能我傳入一個聯(lián)合類型,然后它給返回交叉類型呢?

比如這樣:

都提示出來了肯定是可以的,我們看下砸實現(xiàn)的吧:

聯(lián)合轉交叉函數參數有逆變的性質,也就是類型縮小,比如參數能同時傳 A、B、C 的話,參數類型怎么定義?

肯定是 A、B、C 的交集呀,也就你 A & B & C 的交叉類型,這樣就可以接收 A、B、C 的參數了。

可以利用這個性質實現(xiàn)聯(lián)合轉交叉。

比如這樣:

都提示出來了肯定是可以的,我們看下砸實現(xiàn)的吧:

聯(lián)合轉交叉

函數參數有逆變的性質,也就是類型縮小,比如參數能同時傳 A、B、C 的話,參數類型怎么定義?

肯定是 A、B、C 的交集呀,也就你 A & B & C 的交叉類型,這樣就可以接收 A、B、C 的參數了。

可以利用這個性質實現(xiàn)聯(lián)合轉交叉。

type UnionToIntersection<U> = 
(U extends U ? (x: U) => unknown : never) extends (x: infer R) => unknown
? R
: never

測試一下:

這里的類型參數 U 是傳入的聯(lián)合類型,加一個 U extends U 是為了觸發(fā)分布式條件類型的特性。

什么是分布式條件類型呢?

當類型參數為聯(lián)合類型,并且在條件類型左邊直接引用該類型參數的時候,TypeScript 會把每一個元素單獨傳入來做類型運算,最后再合并成聯(lián)合類型,這種語法叫做分布式條件類型。

比如這樣一個聯(lián)合類型:

type Union = 'a' | 'b' | 'c';

我們想把其中的 a 大寫,就可以這樣寫:

type UppercaseA<Item extends string> = 
Item extends 'a' ? Uppercase<Item> : Item;

回到聯(lián)合轉交叉的這個高級類型:

加一個 U extends U 或者 U extends any 就能觸發(fā)分布式條件類型的特性,讓聯(lián)合類型分成每一個類型單獨傳入做計算,最后把結果合并成聯(lián)合類型。

然后再把它放到函數參數的位置,構造一個函數類型,通過模式匹配的方式提取參數的類型到 infer 聲明的局部變量 R 里返回。

這樣的結果就是交叉類型。

原因上面說過了,函數參數有逆變的性質,傳入聯(lián)合類型會返回交叉類型。

實現(xiàn)了聯(lián)合轉交叉之后,函數重載也就可以寫出來了:

比如三個重載的返回值分別是 Aaa、Bbb、Ccc:

我們想基于這個生成重載的類型定義,傳入聯(lián)合類型返回重載的函數:

就可以這樣寫:

type UnionToOverloadFunction<T extends keyof ReturnValueMap> = 
UnionToIntersection<
T extends any ? (type: T) => ReturnValueMap[T] : never
>;

類型參數 T 是 ReturnValueMap 里的 key,約束為 keyof ReturnValueMap。

通過 T extends any 觸發(fā)聯(lián)合類型在分布式條件類型中的分發(fā)特性,讓 'aaa' 'bbb' 'ccc' 分別傳入做計算,返回構造出的函數類型的聯(lián)合。

我們先單獨測試下這部分:

可以看到返回的是構造出的函數類型的聯(lián)合類型。

然后就用上面的 UnionToIntersection 轉交叉就可以了:

這樣就實現(xiàn)了重載函數的動態(tài)生成:

對比下最開始那種寫法:

是不是清爽多了!而且還可以寫一些動態(tài)邏輯。

總結

ts 函數重載一共有三種寫法:declare function、interface、交叉類型 &。

當重載比較多的時候,直接列出來還是比較麻煩的,這時候可以用類型編程來動態(tài)生成函數重載。

我們實現(xiàn)了聯(lián)合轉交叉,利用了函數參數的逆變性質,也就是當參數可能是多個類型時,會返回它們的交叉類型。

然后又利用分布式條件類型的性質,當傳入聯(lián)合類型時,會把類型單獨傳入做計算,最后把結果合并成聯(lián)合類型。

利用這個實現(xiàn)了傳入聯(lián)合類型返回構造出的函數的聯(lián)合類型,然后再結合聯(lián)合轉交叉就實現(xiàn)了函數重載的動態(tài)生成。

當你寫重載寫的太多的時候,不妨試一下用類型編程的方式動態(tài)生成吧!

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

2018-08-08 14:25:17

2023-04-14 15:44:20

TypeScrip函數重載

2021-03-03 08:05:53

C++項目函數

2020-07-21 18:54:21

Rust類型轉換語言

2024-06-07 15:22:17

False聚合排序

2022-07-29 16:50:30

網絡帶寬

2021-02-01 13:35:28

微信Python技巧

2022-12-06 17:30:04

2022-01-04 06:56:43

面試Java方法重載

2020-11-04 07:36:06

Redis二進制數據庫

2022-07-30 23:45:09

內存泄漏檢測工具工具

2022-10-09 10:02:09

Python3.12

2022-04-21 14:50:50

Python農歷命令

2022-02-28 08:17:24

重載函數JS前端

2010-01-18 16:56:30

C++函數

2009-07-31 16:00:30

C#函數重載

2022-05-17 07:26:33

動畫CSS前端

2023-07-03 16:49:47

5G

2021-11-08 11:02:01

Go函數重載

2011-10-14 10:18:16

信息泄漏
點贊
收藏

51CTO技術棧公眾號