」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 最佳化 TypeScript Curry 函數:從靜態類型到可變參數類型

最佳化 TypeScript Curry 函數:從靜態類型到可變參數類型

發佈於2024-08-28
瀏覽:608

Optimizing a TypeScript Curry Function: From Static Types to Variadic Types

柯里化是一種函數式程式設計技術,它將具有多個參數的函數轉換為一系列函數,每個函數接受一個參數。這種方法對於創建更模組化和可重複使用的函數特別有用,允許部分應用參數。在 TypeScript 中,實現高效率的柯里化函數需要仔細的型別管理,尤其是在處理可變數量的參數時。

在本文中,我們將探討 TypeScript 中 curry 函數的兩種不同實作。第一個使用具有靜態類型的接口,而第二個採用更靈活的方法,使用具有可變類型的單一接口。我們將分析這兩種實作之間的差異,並討論更優化方法的優點。

初始實作:靜態類型介面

定義介面

在第一個實作中,我定義了一系列介面來處理具有不同數量參數的柯里化函數。每個介面對應一個具有特定數量參數的函數:

interface CurryFunction1 {
    (arg1: T1): R;
}

interface CurryFunction2 {
    (arg1: T1): CurryFunction1;
}

interface CurryFunction3 {
    (arg1: T1): CurryFunction2;
}

interface CurryFunction4 {
    (arg1: T1): CurryFunction3;
}

interface CurryFunction5 {
    (arg1: T1): CurryFunction4;
}

interface CurryFunction6 {
    (arg1: T1): CurryFunction5;
}
實現柯里函數

柯里化函數被定義為使用這些介面來柯里化函數,最多有六個參數:

function curry(fn: (arg1: T1, arg2: T2) => R): CurryFunction2;
function curry(fn: (arg1: T1, arg2: T2, arg3: T3) => R): CurryFunction3;
function curry(fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => R): CurryFunction4;
function curry(fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => R): CurryFunction5;
function curry(fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6) => R): CurryFunction6;
function curry(fn: Function) {
    return function curried(...args: any[]) {
        if (args.length >= fn.length) {
            return fn(...args);
        } else {
            return (...args2: any[]) => curried(...args, ...args2);
        }
    };
}
測試柯里函數

然後測試函數以確保它可以在不同數量的參數下正常工作:

function testCurry() {
    const add = (a: number, b: number) => a   b;
    const curriedAdd = curry(add);
    assert(curriedAdd(1)(2) === 3, 'Test curry function with 2 arguments');

    const add3Args = (a: number, b: number, c: number) => a   b   c;
    const curriedAdd3Args = curry(add3Args);
    assert(curriedAdd3Args(1)(2)(3) === 6, 'Test curry function with 3 arguments');
}
實施分析

雖然此實作是清晰且典型的 TypeScript,但它有一些限制。值得注意的是,它需要為每個可能數量的參數定義多個接口,從而使程式碼冗餘且難以維護。此外,處理六個以上的參數將需要添加更多接口,從而增加複雜性。

最佳化實作:具有可變參數類型的單一介面

可變參數類型簡介

為了優化 curry 函數,我採用了一種更動態的方法,使用具有可變參數類型的單一通用介面。這種方法允許處理任意數量的參數,而無需為每種情況定義單獨的介面。

使用可變參數類型實現 Curry 函數

在此最佳化版本中,curry 函數是使用單一通用介面實現的,該介面利用 TypeScript 的可變參數類型來處理任意數量的參數:

type CurryFunction = T extends [infer A, ...infer Rest]
  ? (arg: A) => CurryFunction
  : R;

function curry(fn: (...args: T) => R): CurryFunction {
  return function curried(...args: unknown[]): unknown {
    if (args.length >= fn.length) {
      return fn(...args as T);
    } else {
      return (...args2: unknown[]) => curried(...([...args, ...args2] as unknown[]));
    }
  } as CurryFunction;
}
優化實施的好處
  1. 降低複雜度:透過使用單一通用介面 CurryFunction,此實作無需為每個可能數量的參數建立多個介面。這使得程式碼更加簡潔,更易於維護。

  2. 支援任意數量的參數:利用可變參數類型允許此函數使用任意數量的參數柯里化函數,而無需修改實作。功能更加靈活,適應各種場景。

  3. 改進的類型:動態類型允許 TypeScript 準確推斷參數類型,在開發過程中提供更強的類型檢查,降低錯誤風險,並提高程式碼完成度。

測試最佳化的柯里函數

此版本的 curry 函數也經過測試,以確保其正常運作:

function testCurry() {
    const add = (a: number, b: number) => a   b;
    const curriedAdd = curry(add);
    assert(curriedAdd(1)(2) === 3, 'Test curry function with 2 arguments');

    const add3Args = (a: number, b: number, c: number) => a   b   c;
    const curriedAdd3Args = curry(add3Args);
    assert(curriedAdd3Args(1)(2)(3) === 6, 'Test curry function with 3 arguments');

    const add4Args = (a: number, b: number, c: number, d: number) => a   b   c   d;
    const curriedAdd4Args = curry(add4Args);
    assert(curriedAdd4Args(1)(2)(3)(4) === 10, 'Test curry function with 4 arguments');
}

最佳化 TypeScript 中的 curry 函數示範如何透過採用可變參數類型來改進基於靜態介面的方法。新的實作不僅降低了程式碼複雜性,而且提供了更大的靈活性和更強的類型檢查。這個例子強調了充分利用 TypeScript 的功能來創建更清晰、更模組化和可維護的程式碼的重要性。

從具有多個介面的結構過渡到單一通用介面是理解和應用高級 TypeScript 概念如何帶來更優雅、更有效率的解決方案的一個很好的例子。

版本聲明 本文轉載於:https://dev.to/francescoagati/optimizing-a-typescript-curry-function-from-static-types-to-variadic-types-2ma0?1如有侵犯,請聯繫[email protected]刪除
最新教學 更多>

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3