«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Оптимизация функции карри TypeScript: от статических типов к вариативным типам

Оптимизация функции карри TypeScript: от статических типов к вариативным типам

Опубликовано 28 августа 2024 г.
Просматривать:983

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

Карринг — это метод функционального программирования, который преобразует функцию с несколькими аргументами в последовательность функций, каждая из которых принимает один аргумент. Этот подход особенно полезен для создания более модульных и повторно используемых функций, позволяющих частично применять аргументы. В TypeScript реализация эффективной функции карри требует тщательного управления типами, особенно при работе с переменным количеством аргументов.

В этой статье мы рассмотрим две разные реализации функции карри в TypeScript. Первый использует интерфейсы со статическими типами, а второй использует более гибкий подход, используя один интерфейс с переменными типами. Мы проанализируем различия между этими двумя реализациями и обсудим преимущества более оптимизированного подхода.

Начальная реализация: интерфейсы со статическими типами

Определение интерфейсов

В первой реализации я определил серию интерфейсов для обработки каррированных функций с различным количеством аргументов. Каждый интерфейс соответствует функции с определенным количеством аргументов:

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, она имеет некоторые ограничения. Примечательно, что для каждого возможного числа аргументов требуется определение нескольких интерфейсов, что делает код избыточным и усложняет его поддержку. Кроме того, обработка более шести аргументов потребует добавления большего количества интерфейсов, что увеличит сложность.

Оптимизированная реализация: единый интерфейс с переменными типами

Введение в вариативные типы

Чтобы оптимизировать функцию карри, я применил более динамичный подход, используя единый универсальный интерфейс с переменными типами. Этот подход позволяет обрабатывать произвольное количество аргументов без необходимости определять отдельный интерфейс для каждого случая.

Реализация функции карри с переменными типами

В этой оптимизированной версии функция карри реализована с использованием единого универсального интерфейса, который использует вариативные типы 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 точно определять типы аргументов, обеспечивая более строгую проверку типов во время разработки, снижая риск ошибок и улучшая завершение кода.

Тестирование оптимизированной функции карри

Эта версия функции карри также проверена на правильность работы:

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 демонстрирует, как можно улучшить подход, основанный на статических интерфейсах, за счет использования вариативных типов. Новая реализация не только снижает сложность кода, но также обеспечивает большую гибкость и более строгую проверку типов. Этот пример подчеркивает важность полного использования возможностей TypeScript для создания более чистого, модульного и удобного в обслуживании кода.

Переход от структуры с несколькими интерфейсами к одному универсальному интерфейсу — отличный пример того, как понимание и применение передовых концепций TypeScript может привести к более элегантным и эффективным решениям.

Заявление о выпуске Эта статья воспроизведена по адресу: https://dev.to/francescoagati/optimizing-a-typescript-curry-function-from-static-types-to-variadic-types-2ma0?1 Если есть какие-либо нарушения, свяжитесь с Study_golang. @163.com удалить
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3