Изменение параметров и типов возвращаемых значений обобщенной функции TypeScript

Вопрос или проблема

Могу ли я сделать все аргументы функции доступными только для чтения и преобразовать эту функцию в асинхронную?

Например:

declare function foo<T>(bar: T, baz: T[]): T;

Преобразовать в

declare function foo<T>(bar: Readonly<T>, baz: readonly T[]): Promise<T>;

Я попробовал это, что работает для не генеративных функций:

type ReadonlyArrayItems<T> = { [P in keyof T]: Readonly<T[P]> };
type MakeFunctionAsync<T> = (...args: ReadonlyArrayItems<Parameters<T>>) => Promise<ReturnType<T>>;
type Foo = MakeFunctionAsync<typeof foo>;

Однако новый тип функции Foo нарушает генеративную функцию, превращая все исходные типы T в unknown.

Ответ или решение

Чтобы преобразовать параметры обобщенной функции в readonly и изменить ее на асинхронную функцию, нам нужно будет аккуратно создать новый тип функции, сохраняя при этом оригинальный тип T. Ниже я объясню, как это сделать.

Исходная функция объявлена следующим образом:

declare function foo<T>(bar: T, baz: T[]): T;

Наша цель — преобразовать эту функцию в:

declare function foo<T>(bar: Readonly<T>, baz: readonly T[]): Promise<T>;

Для успешного выполнения этой задачи мы воспользуемся типами TypeScript для создания нового типа функции. Мы определим два вспомогательных типа: один для преобразования параметров функции в readonly, а другой для того, чтобы сделать функцию асинхронной. Тем не менее, нам нужно будет сохранить обобщенный тип T.

Вот как это можно сделать:

// Вспомогательный тип для преобразования параметров в Readonly
type ReadonlyArrayItems<T> = { 
  [P in keyof T]: Readonly<T[P]>; 
};

// Основной тип для создания асинхронной функции с параметрами Readonly
type MakeFunctionAsync<F extends (...args: any[]) => any> = 
  (...args: ReadonlyArrayItems<Parameters<F>>) => Promise<ReturnType<F>>;

// Применение типа MakeFunctionAsync к функции foo
type Foo = MakeFunctionAsync<typeof foo>;

Давайте разберемся, как это работает:

  1. ReadonlyArrayItems: Этот тип принимает тип T, который является массивом параметров функции, и создает новый тип, где каждый элемент массива является Readonly.

  2. MakeFunctionAsync: Этот обобщенный тип принимает функцию F. Он получает типы параметров функции F с помощью Parameters<F> и применяет к ним ReadonlyArrayItems, чтобы все параметры стали readonly. Также он возвращает Promise от типа возвращаемого значения оригинальной функции с помощью ReturnType<F>.

Когда мы применяем MakeFunctionAsync к функции foo, мы получаем новый тип Foo, который соответствует нашей новой требуемой сигнатуре.

Подводя итог, данный подход позволяет нам сохранить обобщенность типа T и в то же время преобразовать параметры функции в readonly и вернуть Promise. Теперь вы можете использовать тип Foo в своем коде, и он будет отражать необходимую форму асинхронной функции с параметрами readonly.

Оцените материал
Добавить комментарий

Капча загружается...