Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript wrapping function with generic type

How can I wrap a function without changing its generic type in Typescript?

function x() {
  console.log('Original Function');
}

function wrapper<T extends Function>(func: T): T {
  // Typescript compiler error:
  // Type '() => void' is not assignable to type 'T'.
  return () => {
    console.log('Wrapped Function');
    func.call(null);
  }
}

const xWrapped = wrapper(x);
xWrapped(); // logged 'Wrapped Function' & 'Original Function'
like image 948
PRAISER Avatar asked Dec 08 '22 17:12

PRAISER


1 Answers

Here's an alternative that preserves the argument and returns types of the inner function without depending on variadic types.

function x(message: string): void {
    console.log(`inner ${message}`);
}

export function wrapper<Args extends any[], Return>(
    operation: (...operationParameters: Args) => Return, 
    ...parameters: Args
): Return {
    console.log(`outer `);

    return operation(...parameters);
}

x("abc");
wrapper(x, "xyz");

// output:
//
// inner abc
// outer
// inner xyz

When wrapper is called with x, the TS compiler infers its type as function wrapper<[string], void>(operation: (operationParameters_0: string) => void, parameters_0: string): void.

If you try to call wrapper(x, 123), it fails with beautiful type safety: Argument of type '123' is not assignable to parameter of type 'string'.

like image 122
Gordon Avatar answered Dec 11 '22 09:12

Gordon