title: Why does TypeScript not infer types for some piped functions?
body: <p>Update Feb 20, 2018: posted this as an <a href="https://github.com/Microsoft/TypeScript/issues/22051" rel="noreferrer">issue on GitHub</a>.</p>
  
  <p>Update Feb 28: closed that issue in favor of <a href="https://github.com/Microsoft/TypeScript/issues/22081" rel="noreferrer">a new one</a>.</p>
  
  <p>In the following code snippet, if you look at the last two lines, TypeScript shows an error in the first one, and correctly infers types in the second one, although the difference is only the order in which the functions are piped.</p>
  
  <pre><code>const pipe = &lt;A, B, C&gt;(
    x: A,
    a: (x: A) =&gt; B, 
    b: (x: B) =&gt; C,
  ) =&gt; b(a(x));
  
  // This just calls the function passed as argument.
  const call = &lt;A, B&gt;(f: (x: A) =&gt; B) =&gt; (x: A) =&gt; f(x)
  
  const a = pipe(1, x =&gt; x + 1, call(x =&gt; x + 1));
  const b = pipe(1, call(x =&gt; x + 1), x =&gt; x + 1);
  </code></pre>
  
  <p>I use TypeScript 2.7.1 in the strict mode (including strictFunctionTypes), however the strict mode doesn't seem to matter here. <a href="https://www.typescriptlang.org/play/#src=const%20pipe%20%3D%20%3CA%2C%20B%2C%20C%3E(%0D%0A%20%20x%3A%20A%2C%0D%0A%20%20a%3A%20(x%3A%20A)%20%3D%3E%20B%2C%20%0D%0A%20%20b%3A%20(x%3A%20B)%20%3D%3E%20C%2C%0D%0A)%20%3D%3E%20b(a(x))%3B%0D%0A%0D%0Aconst%20call%20%3D%20%3CA%2C%20B%3E(f%3A%20(x%3A%20A)%20%3D%3E%20B)%20%3D%3E%20(x%3A%20A)%20%3D%3E%20f(x)%0D%0A%0D%0Aconst%20a%20%3D%20pipe(1%2C%20x%20%3D%3E%20x%20%2B%201%2C%20call(x%20%3D%3E%20x%20%2B%201))%3B%0D%0Aconst%20b%20%3D%20pipe(1%2C%20call(x%20%3D%3E%20x%20%2B%201)%2C%20x%20%3D%3E%20x%20%2B%201)%3B%0D%0A" rel="noreferrer">Here is this snippet on TypeScript playground</a>.</p>
  
  <p>It is a problem that I often run into when working with RxJS, since in RxJS there is a similar <code>pipe</code> method and I pass arrow functions to it when using creation operators (like <code>obs =&gt; merge(obs, otherObs)</code>). Usually it's easy to work around this problem by specifying the argument type, but I would like to understand the logic behind this. Why is TypeScript able to infer the type in one case but not in the other?</p>