0no-co / wonka

🎩 A tiny but capable push & pull stream library for TypeScript and Flow
MIT License
704 stars 30 forks source link

Type inference is incorrect for `pipe(source, consumer)`, if consumer returns a function #170

Open pjeby opened 10 months ago

pjeby commented 10 months ago

Currently, the typings for pipe() are arranged in such a way that the Source-specific patterns take precedence over the generic consumer, causing pipe(source, consumer) to be typed as Source<unknown> if consumer returns a function. A trivial example:

// x is inferred to be Source<unknown>, but should be `() => number`
let x = pipe(empty, src => () => 42)

However, as far as I can tell, all the Source-specific typings aren't needed, since the actual pipe() implementation is generic and can take any functions, so the typings could just be e.g.:

interface pipe {
  /* pipe definitions for source + operators composition */

  <T, A>(source: T, op1: UnaryFn<T, A>): A;

  <T, A, B>(
    source: T,
    op1: UnaryFn<T, A>,
    op2: UnaryFn<A, B>
  ): B;

  // ...

  <T, A, B, C, D, E, F, G, H>(
    source: T,
    op1: UnaryFn<T, A>,
    op2: UnaryFn<A, B>,
    op3: UnaryFn<B, C>,
    op4: UnaryFn<C, D>,
    op5: UnaryFn<D, E>,
    op6: UnaryFn<E, F>,
    op7: UnaryFn<F, G>,
    op8: UnaryFn<G, H>
  ): H;
}

This fully-generic typing is shorter and does not get confused about consumers that return functions, and lets you pipe anything through anything.

Would you like a PR for this?

aviral-spotnana commented 5 months ago

Is there any update on this from the maintainers? @kitten (sorry for the spammy tag)