Can't return a function from function that returns a constrained generic type

Viewed 29

Consider this Flow-annotated function:

// @flow
type AnyFunction = (...args: Array<any>) => any;
function wrap<FuncType: AnyFunction>(innerFunc: FuncType): FuncType {
  return (...args) => innerFunc.apply(this, args);
}

AnyFunction is a type that matches any function, as mentioned in the official docs. wrap just returns a function that's exactly equivalent to the one passed in as an argument, so it should be the same type. I would think this should be legal, since wrap is defined to return the same type as its argument.

Flow gives the following error:

Cannot return function because function [1] is incompatible with FuncType [2].

     1│ // @flow
     2│ type AnyFunction = (...args: Array<any>) => any;
 [2] 3│ function wrap<FuncType: AnyFunction>(innerFunc: FuncType): FuncType {
 [1] 4│   return (...args) => innerFunc.apply(this, args);
     5│ }

I'm afraid the answer might be something like "you can't do that because there are no subtype relationships between different function types", but I'm not sure, and I'm not sure why that would have to be the case.

I've even tried simplifying it down to e.g.

/* @flow */
function x<FuncType: () => number>(): FuncType {
  return () => Math.random();
}

but it still gives the same error.

Why do I get these errors, and is there any way to fix it in the first example?

(I do have a practical reason for wanting this; obviously the example as shown isn't very useful, but I was trying to write a function that would wrap any function in a try/catch clause, and do some additional work if it caught an exception.)

UPDATE: This is allowed:

// @flow
type AnyFunction = (...args: Array<any>) => any;
function wrap<FuncType: AnyFunction>(innerFunc: FuncType): FuncType {
  return innerFunc;
}

i.e., returning the same function, instead of wrapping it in an arrow function. So maybe Flow just fails to infer that the type of the function (...args) => innerFunc.apply(this, args) is always the same as the type of innerFunc?

0 Answers
Related