Вопрос или проблема
Могу ли я сделать все аргументы функции доступными только для чтения и преобразовать эту функцию в асинхронную?
Например:
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>;
Давайте разберемся, как это работает:
-
ReadonlyArrayItems: Этот тип принимает тип
T
, который является массивом параметров функции, и создает новый тип, где каждый элемент массива являетсяReadonly
. -
MakeFunctionAsync: Этот обобщенный тип принимает функцию
F
. Он получает типы параметров функцииF
с помощьюParameters<F>
и применяет к нимReadonlyArrayItems
, чтобы все параметры сталиreadonly
. Также он возвращаетPromise
от типа возвращаемого значения оригинальной функции с помощьюReturnType<F>
.
Когда мы применяем MakeFunctionAsync
к функции foo
, мы получаем новый тип Foo
, который соответствует нашей новой требуемой сигнатуре.
Подводя итог, данный подход позволяет нам сохранить обобщенность типа T
и в то же время преобразовать параметры функции в readonly
и вернуть Promise
. Теперь вы можете использовать тип Foo
в своем коде, и он будет отражать необходимую форму асинхронной функции с параметрами readonly
.