title: TypeScript 3.7 recursive type gives "type instantiation is excessively deep and possibly infinite"
body: <p>I'm trying to code a variadic <code>pipe</code> function which composes an arbitrary number of one-argument pure functions.
  This typing should check that the return type of one function is the argument type of the next and so on.</p>
  
  <p>I would expect this to work in TypeScript 3.7 which introduces recursive types but somehow it doesn't work and gives the error:</p>
  
  <p><code>TS2589: type instantiation is excessively deep and possibly infinite</code></p>
  
  <p>Here's my code:</p>
  
  <pre><code>type Tail&lt;T extends any[]&gt; = ((...t: T) =&gt; void) extends ((x: any, ...u: infer U) =&gt; void) ? U : never;
  
  type Pipe&lt;FNS extends unknown[]&gt; = FNS extends [(a: infer A) =&gt; infer B, (b: infer B) =&gt; infer C] ? C :
                                   FNS extends [(a: infer A) =&gt; infer B, (b: infer B) =&gt; infer C, Pipe&lt;[...Tail&lt;FNS&gt;[]]&gt;] ? C : never;
  </code></pre>
  
  <p>The <code>FNS</code> type represents the array of pure functions and the <code>Tail</code> type should make sure that only the tail of this array is returned, but still the compiler marks this as an infinite loop.</p>
  
  <p>Usage example:</p>
  
  <pre><code>const numToString = (n: number): string =&gt; n.toString();
  const toUpper = (s: string): string =&gt; s.toUpperCase();
  
  // this works, Foo evaluates to string
  type Foo = Pipe&lt;[typeof numToString, typeof toUpper]&gt;;
  
  // this doesn't work, Foo is not evaluated
  type Foo = Pipe&lt;[typeof numToString, typeof toUpper, typeof toUpper]&gt;;
  </code></pre>
  
  <p>The error is on this part:</p>
  
  <pre><code>Pipe&lt;[...Tail&lt;FNS&gt;[]]&gt;
  </code></pre>
  
  <p>Why is this infinite? What am I missing?</p>