ramda/types

What to do about transducers

Harris-Miller opened this issue · 0 comments

Transducers are a particularly challenging thing to do in typescript do to how "functions that act as transformers" are isomorphic to them

const a =  [1, 2, 3];

const f = R.compose(
  R.map(R.multiply(2)),
  R.map(R.add(3)),
);

// compose runs the array values through the first map and then the second
f(a); // [5,8,11]

// transduce runs the init transformer into the multiple transformers into the add transformer
R.transduce(f, R.flip(R.append), [], a); // [9, 12, 15]

Now while the above example works fine, once you start transitioning through the types it gets weird quickly

const a =  [1, 2, 3];

// this is completely contrived but gets the point across
const f = R.compose(
  R.map(R.toString()),
  R.map(R.add(3)),
);

f(a); // ['3', '6', '9'];

// because now `toString` is processed first, `add` does string concatenation
R.transduce(f, R.flip(R.append), [], a); // ['13, '23', '33']

Typescript doesn't have "look-ahead" capabilities where it can see where a function is used to determine what its type should be for isomorphic behavior like this

The only way around this that I can think of is to have a separate function for compose and pipe that is typed specifically to the order of operation here