Оставшиеся параметры (...rest) в TypeScript

Есть функция createRequest, которая принимает в себя функцию func, и возвращает асинхронную функцию action, которая внутри себя будет вызывать функцию func. Как сделать так, что бы функция action принимала в себя только параметры func, будто вызывается непосредственно функция func?

function createRequest(func: Function): Function {
      // входящие параметры функции action должны соответствовать 
      // входящим параметрам функции func
      return async function action(...args: any) {
        // other code...
        func(...args);
        // ...other code
      }
    }

Например:

function A (a: number, b: string) {
  return [a, b];
}

const B = createRequest(A);

B(1, 'a'); // корректный вызов, передающиеся параметры правильного типа
B(1, 2); // некорректный вызов, typescript должен выдавать ошибку типов

На данный момент код работает, но нужно проверка типов TypeScript.

Наткнулся на Parameters<Type>, однако мне не совсем понятно, как это применить, и подходит ли это вообще.


Ответы (2 шт):

Автор решения: Grundy

Для использования Parameters<T>, нужно чтобы T был совместим с сигнатурой (...args: any): any.

Поэтому в данном случае не получится использовать тип Function.

Однако можно сделать функцию createRequest шаблонной

createRequest<T>

и добавить, что T расширяет (...args: any): any

createRequest<T extends (...args:any)=>any>(func: T)

Так же можно добавить тип возвращаемого значения

function createRequest<T extends (...args:any)=>any>(func: T): (...args:Parameters<T>)=>Promise<void> {

Теперь, для возвращаемой функции достаточно просто указать тип параметров:

return async function action(...args: Parameters<T>) {

теперь, чтобы заработал

func(...args);

Нужно указать, что тип у args - массив, для этого нужно изменить либо в обертке

createRequest<T extends (...args:any[])=>any>(func: T)

либо в возвращаемой функции

    return async function action(...args: Parameters<T>[]) {

Итоговый код может выглядеть так:

function createRequest<T extends (...args:any[])=>any>(func: T): (...args:Parameters<T>)=>Promise<void> {
      // входящие параметры функции action должны соответствовать 
      // входящим параметрам функции func
      return async function action(...args: Parameters<T>) {
        // other code...
        func(...args);
        // ...other code
      }
    }

function A (a: number, b: string) {
  return [a, b];
}

const B = createRequest(A);

B(1, 'a'); // корректный вызов, передающиеся параметры правильного типа
B(1, 2); // некорректный вызов, typescript должен выдавать ошибку типов

Пример для запуска

→ Ссылка
Автор решения: Qwertiy

Песочница

function createRequest<Args extends any[]>(func: (...args: Args) => void) {
    return async function action(...args: Args) {
        func(...args);
    }
}

function f(a: number, b: string) {
  return [a, b];
}

const g = createRequest(f);

g(1, 'a'); // ok
g(1, 2);   // Argument of type 'number' is not assignable to parameter of type 'string'.
→ Ссылка