title: TypeScript: How to write an asyncPipe function for asynchronous function composition?
body: <p>I'm recently exploring TypeScript again. One of it's key limitations seems to be the incapability of typing function composition. Let me first show you the JavaScript code. I'm trying to type this:</p>
  
  <pre class="lang-js prettyprint-override"><code>const getUserById = id =&gt; new Promise((resolve, reject) =&gt; id === 1
    ? resolve({ id, displayName: 'Jan' })
    : reject('User not found.')
  );
  const getName = ({ displayName }) =&gt; displayName;
  const countLetters = str =&gt; str.length;
  const asyncIsEven = n =&gt; Promise.resolve(n % 2 === 0);
  
  const asyncPipe = (...fns) =&gt; x =&gt; fns.reduce(async (y, f) =&gt; f(await y), x);
  
  const userHasEvenName = asyncPipe(
      getUserById,
      getName,
      countLetters,
      asyncIsEven
  );
  
  userHasEvenName(1).then(console.log);
  // ↳ false
  userHasEvenName(2).catch(console.log);
  // ↳ 'User not found.'
  </code></pre>
  
  <p>Here <code>asyncPipe</code> composes regular functions as well as promises in anti-mathematical order (from left to right). I would love to write an <code>asyncPipe</code> in TypeScript, that knows about the input and output types. So <code>userHasEvenName</code> should know, that it takes in a number and returns a <code>Promise&lt;boolean&gt;</code>. Or, if you comment out <code>getUserById</code> and <code>asyncIsEven</code> it should know that it takes in a <code>User</code> and returns a number.</p>
  
  <p>Here are the helper functions in TypeScript:</p>
  
  <pre><code>interface User {
      id: number;
      displayName: string;
  }
  
  const getUserById = (id: number) =&gt; new Promise&lt;User&gt;((resolve, reject) =&gt; id === 1
      ? resolve({ id, displayName: 'Jan' })
      : reject('User not found.')
  );
  const getName = ({ displayName }: { displayName: string }) =&gt; displayName;
  const countLetters = (str: string) =&gt; str.length;
  const asyncIsEven = (n: number) =&gt; Promise.resolve(n % 2 === 0);
  </code></pre>
  
  <p>I would love to show you all my approaches for <code>asyncPipe</code> but most were way off. I found out that in order to write a <code>compose</code> function in TypeScript, you have to <a href="https://github.com/reduxjs/redux/blob/master/src/compose.ts" rel="noreferrer">heavily overload</a> it because TypeScript can't handle backwards inference and <code>compose</code> runs in mathematical order. Since <code>asyncPipe</code> composes from left to right, it feels like it's possible to write it. I was able to explicitly write a <code>pipe2</code> that can compose two regular functions:</p>
  
  <pre><code>function pipe2&lt;A, B, C&gt;(f: (arg: A) =&gt; B, g: (arg: B) =&gt; C): (arg: A) =&gt; C {
      return x =&gt; g(f(x));
  }
  </code></pre>
  
  <p>How would you write <code>asyncPipe</code> that asynchronously composes an arbitrary amount of function or promises and correctly infers the return type?</p>