I'm been trying to figure out the correct type definitions for the compose function, see the discussion on github and the discussion on discord.
Consider the example below where I've distilled the compose and pipe type definitions into a concise example. The definitions work correctly for pipe, but not for compose despite them being almost identical (only the order of f1 and f2 is different).
function compose2<R0, R1, R2>(
f2: (a: R1) => R2,
f1: (a: R0) => R1,
): (a: R0) => R2 {
return (x: R0) => f2(f1(x));
}
const composeTest = compose2(
R.defaultTo('fallback'),
R.nth(1) // << typescript is already confused
)([1, 2]);
function pipe2<R0, R1, R2>(
f1: (a: R0) => R1,
f2: (a: R1) => R2,
): (a: R0) => R2 {
return (x: R0) => f2(f1(x));
}
// correctly number | string
const pipeTest = pipe2(
R.nth(1),
R.defaultTo('fallback'),
)([1, 2]);
What I think this boils down to is that typescript is doing it's inference in the order of the code instead of building a type dependency tree and evaluating it in that order. Is this accurate?
Does anyone have an insight into this problem?