首先我們開啟VSCode , 按照下面動手做.
繼續回到 add 方法, 一般的 add 加法函數有兩個輸入參數回傳值是數字, 我們先宣告如下
function add(a: number, b: number): number;
之前上面有說明柯里化是...
柯里化後的新的函數, 輸入只有一個參數, 回傳值也是函數
然後我們要將 add 柯里化, 所以再加以下宣告
function add(a: number): (b: number) => number;
(b: number) => number 是一個函數宣告, 表明有一個輸入參數 b, 回傳值是 number
然後我們建立真正的add 加法函數, 輸入參數是無限個, 裡面不考慮加法如何實做, 我們先故意回傳 null
function add(...args: any[]): any {
return null as any;
}
整個程式碼應該如下
function add(a: number, b: number): number;
function add(a: number): (b: number) => number;
function add(...args: any[]): any {
return null as any;
}
這是Typescript 的多載函數宣告方法.
函數多載 是程式語言中允許建立很多個函數名稱相同, 但輸入參數類型可以不同, 數量也能不同, 甚至回傳值類型也可以不同
現在我們輸入
type OverloadedAdd = typeof add;
我們用滑鼠移到 OverloadedAdd 上, 你會看到Typescript 描述 add 的柯里化函數的內容, 如下所示
type OverloadedAdd = {
(a: number, b:number): number;
(a: number): (b: number) => number;
};
現在我們知道Typescript 對於 add 函數的柯里化宣告定義是甚麼樣子了.
清除所有程式碼, 這次我們輸入 CurryAdd 柯里化
type CurryAdd = {
(a: number, b:number): number;
(a: number): (b: number) => number;
};
然後我們要重構一下, 提取這個部分
(b: number) => number
變成下面程式碼
type CurryAdd1 = (b: number) => number;
因為只有一個參數, b 名稱很難看, 我們修改名稱為 a
type CurryAdd1 = (b: number) => number;
最後上述程式碼重構完後, 完整程式碼如下
type CurryAdd1 = (a: number) => number;
type CurryAdd2 = {
(a: number, b:number): number;
(a: number): CurryAdd1;
};
觀察上面的程式碼, 你可以發現 type CurryAdd2 第一行是帶有兩個參數的原始宣告, 第二行是柯里化宣告.
故假如我們要 CurryAdd2 加法函數能夠接受三個參數.
所以我們可以這樣做, 建立 CurryAdd3 第一行表示要三個參數, 然後後面加上兩個 Curry 柯里化函數
type CurryAdd3 = {
(a: number, b:number, c:number): number;
(a: number, b:number): CurryAdd1;
(a: number): CurryAdd2;
};
到目前為止, 我們可以手動建立輸入 n 個參數的 Curry 柯里化函數.
現在思維跳回一般的物件導向語言, 實際上我們的一般物件函數的定義, 並非只有兩個參數, 或三個參數. 如果我們手動輸入把這些物件導向函數柯里化為新的函數.
遇到物件導向函數有 5 個輸入參數, 那我們就得手工敲很多程式碼才能夠將它柯里化....
所以我們必須有一種方法可以重複做到這樣的功能.
幸好Typescript 有提供 "條件類型" (Conditional Types), 它允許我們根據條件判斷, 而回傳類型.
以下是Typescript 條件類型判斷語法
type ConditionalType<T> =
T extends SomeType ? TypeA : TypeB;
然後當我們輸入以下程式碼, Typescript 就會判斷 TypeX 的類型是不是 SomeType , 如果是的話就回傳 TypeA, 不是的話就回傳 TypeB .
const x: ConditionalType<TypeX>;
所以在我們的 add 加法柯里化例子, 我們可以定義新的 CurryAddX 的條件類型
type CurryAddX<T> =
T extends [number, number, number] ? CurryAdd3 :
T extends [number, number] ? CurryAdd2 :
T extends [number] ? CurryAdd1 :
unknown
;
這個 CurryAddX 條件類型檢查 T 是否有匹配 [number, number, number] 三個參數, 有的話就給 CurryAdd3 柯里化函數.
沒有的話又檢查 T 是否有匹配 [number, number] 兩個參數, 有的話就給 CurryAdd2 柯里化函數.
以此類推到 unknown 未知結果.
unknown 是 Typescript 提供的類型, 表示是未知類型. 但是更安全的作法是動態檢查它的類型.