title: Infer class constructor arguments from instance of class in TypeScript
body: <p>I have a singleton class that is an extension of a 20x20 array.  (I'm making a word search.)  I discovered this delightful syntax for exporting a singleton class's instance maintaining both the name of the instance and that of the class:</p>
  <pre class="lang-ts prettyprint-override"><code>const Grid = new class Grid extends Array&lt;string[]&gt; {
    constructor(private readonly size = 20) {
      super(size);
      // ...
    }
  
    // ...
  };
  
  export default Grid;
  </code></pre>
  <p>Huzzah, that works great.  Now to test.  To make things manageable, I want to create a new grid with a much smaller size (maybe 8x8).  In JavaScript, retrieving the constructor is easy.</p>
  <pre class="lang-js prettyprint-override"><code>import Grid from './grid';
  
  const GridConstructor = Grid.constructor;
  
  it('does a thing', () =&gt; {
    const testGrid = new GridConstructor(8);
  });
  </code></pre>
  <p>Since I <em>know</em> what the argument expects, yes, I can just do that and declare <code>GridConstructor</code> as</p>
  <pre class="lang-ts prettyprint-override"><code>const GridConstructor: new(size: number) =&gt; typeof Grid = Grid.constructor;
  </code></pre>
  <p>That, of course, is the <em>reasonable</em> solution.  I am not a reasonable person though, and must type ALL THE THINGS using the TypeScript typing engine.  (Okay, so I really just like learning.  Who knows when this may be useful?)
  TypeScript thinks that <code>Grid.constructor</code> is of type <code>Function</code>.  As far as I can tell, it doesn't have any information on what that function's shape is.</p>
  <p>Is it possible to infer that shape?</p>
  <p>The best I've come up with is:</p>
  <pre class="lang-ts prettyprint-override"><code>type Constructor&lt;T extends { constructor: new(...args: any[]) =&gt; any; }&gt; = 
    new(...args: ConstructorParameters&lt;T['constructor']&gt;) =&gt; InstanceType&lt;T['constructor']&gt;;
  
  const GridConstructor: Constructor&lt;typeof Grid&gt; = Grid.constructor;
  </code></pre>
  <p>This results in the error:</p>
  <blockquote>
  <p><code>Type 'Grid' does not satisfy the constraint '{ constructor: new (...args: any[]) =&gt; any; }'.</code></p>
  </blockquote>
  <p><a href="https://www.typescriptlang.org/play?#code/MYewdgzgLgBA4gJwJYBMYF4ZgKYHcbAA2AhhBPMmtgB5TZgrkCCCCxAngDzTJgDmAbQC6APhgBvALAAoGAXA8ArsCggEACgAOyAG7E6MBNmIpwhdjAhIAXtgwwATAAYAlBJly5ERZuwarti4A3B4wAL4yEdIyUOy+MADCClAIyqoInAAqMDR0DOTi8pApaWoAXFh46gB0tcQIfBAVxGDswm7oYi0WYWLooTi4NXUNTYnJqSpqAAr1xAC22HQIEFkCAOSgxZPp66IdYgCSxS3A2Jlx2GubE6UIeyIh0dJb0BSoSdt3FZ9KUxmxXwgABm7xQfTB1VeJX+Txk0JgdGgiFQ9kGYN+MPS6gAHMEgA" rel="nofollow noreferrer">TypeScript Playground</a></p>