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?