Closed
Description
TypeScript Version: 3.6.0-dev.20190603
Search Terms:
Compose doesn't infer generic types of arguments.
Code
function compose<F, G, R>(f: (x: F) => R, g: (y: G) => F): (y: G) => R {
return x => f(g(x));
}
function toArray<T extends any>(element: T): T[] {
return [element];
}
const doubleArray = compose(
toArray,
toArray,
)(1);
(11,3): error TS2345: Argument of type '<T extends any>(element: T) => T[]' is not assignable to parameter of type '(y: unknown) => T'.
Type 'unknown[]' is not assignable to type 'T'.
'unknown[]' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'any'.
Expected behavior:
I expect doubleArray
to be inferred as number[][]
.
Actual behavior:
It is inferred as unknown
.
I'm also not sure how to help typescript, to infer this correctly, for example, this doesn't work:
const doubleArray = compose(
toArray<number>,
toArray<number>,
)(1);
Playground Link:
Playground
Related Issues:
#10247
Interestingly, if we define compose from left to right, instead of the standard mathematical composition, it actually works:
function compose<F, G, R>(f: (x: F) => G, g: (y: G) => R): (x: F) => R {
return x => g(f(x));
}
I choose a very generic example, but the code that I actually try to type are HOC with react.
For example:
export const Container = compose(
connect(...),
withStyles(...),
withLoader(LoaderComponent),
withTranslations
)(Component);
This code doesn't get inferred correctly, and also here, with the left to right compose function it does get inferred.