<p dir="auto">I have a function that takes a class constructor as a parameter, and returns another class constructor of the same type. Internally, the provided constructor is subclassed and augmented, and the subclass is returned.</p>
<p dir="auto">I'm having trouble finding a way to express this function in a generic, strongly-typed manner. Note the <code class="notranslate">//ERROR</code> comment in the repro code below:</p>
<p dir="auto">Repro code:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// Base type of the family of classes operated on by the augment() function
class FooClass { /*...*/ }


// ========== Works, but is not generic ==========
function augment(SuperClass: typeof FooClass): typeof FooClass {
    class SubClass extends SuperClass {
        /*...*/
    }
    return SubClass;
}
var FooClass2 = augment(FooClass);


// ========== Generic, but does not compile ==========
function genericAugment&lt;T extends typeof FooClass&gt;(SuperClass: T): T {
    class SubClass extends SuperClass { //ERROR: Type 'T' is not a constructor function type
        /*...*/
    }
    return SubClass;
}"><pre class="notranslate"><span class="pl-c">// Base type of the family of classes operated on by the augment() function</span>
<span class="pl-k">class</span> <span class="pl-smi">FooClass</span> <span class="pl-kos">{</span> <span class="pl-c">/*...*/</span> <span class="pl-kos">}</span>


<span class="pl-c">// ========== Works, but is not generic ==========</span>
<span class="pl-k">function</span> <span class="pl-en">augment</span><span class="pl-kos">(</span><span class="pl-smi">SuperClass</span>: <span class="pl-k">typeof</span> <span class="pl-smi">FooClass</span><span class="pl-kos">)</span>: <span class="pl-k">typeof</span> <span class="pl-smi">FooClass</span> <span class="pl-kos">{</span>
    <span class="pl-k">class</span> <span class="pl-smi">SubClass</span> <span class="pl-k">extends</span> <span class="pl-smi">SuperClass</span> <span class="pl-kos">{</span>
        <span class="pl-c">/*...*/</span>
    <span class="pl-kos">}</span>
    <span class="pl-k">return</span> <span class="pl-smi">SubClass</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>
<span class="pl-k">var</span> <span class="pl-smi">FooClass2</span> <span class="pl-c1">=</span> <span class="pl-en">augment</span><span class="pl-kos">(</span><span class="pl-smi">FooClass</span><span class="pl-kos">)</span><span class="pl-kos">;</span>


<span class="pl-c">// ========== Generic, but does not compile ==========</span>
<span class="pl-k">function</span> <span class="pl-en">genericAugment</span><span class="pl-c1">&lt;</span><span class="pl-smi">T</span> <span class="pl-k">extends</span> <span class="pl-k">typeof</span> <span class="pl-smi">FooClass</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-smi">SuperClass</span>: <span class="pl-smi">T</span><span class="pl-kos">)</span>: <span class="pl-smi">T</span> <span class="pl-kos">{</span>
    <span class="pl-k">class</span> <span class="pl-smi">SubClass</span> <span class="pl-k">extends</span> <span class="pl-smi">SuperClass</span> <span class="pl-kos">{</span> <span class="pl-c">//ERROR: Type 'T' is not a constructor function type</span>
        <span class="pl-c">/*...*/</span>
    <span class="pl-kos">}</span>
    <span class="pl-k">return</span> <span class="pl-smi">SubClass</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">I've tried a few other variations, but can't seem to find a way to express this pattern.</p>
<p dir="auto">Is there any way to do it?</p>
<p dir="auto">There appears to be some kind of internal "class" type that is impossible to represent generically:</p>
<p dir="auto">You can see a live version here: <a href="http://goo.gl/exBzY6" rel="nofollow">http://goo.gl/exBzY6</a></p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function IdentifiableSubclass&lt;T extends What?&gt;(SuperClass: T) {
  return class extends T {
    public _id = null;
  }
} 

class Thing {
  public hello = null;
  /* impl */
}

const IdentifiableThing = IdentifiableSubclass(Thing);

class ChildThing extends IdentifiableThing {

}

let child = new ChildThing();
child.hello; // TS does not understand that this exists
child._id;   // TS understands that this exists"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-smi">IdentifiableSubclass</span><span class="pl-c1">&lt;</span><span class="pl-smi">T</span> <span class="pl-k">extends</span> <span class="pl-smi">What</span>?<span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-smi">SuperClass</span>: <span class="pl-smi">T</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">return</span> <span class="pl-k">class</span> <span class="pl-k">extends</span> <span class="pl-smi">T</span> <span class="pl-kos">{</span>
    <span class="pl-k">public</span> <span class="pl-c1">_id</span> <span class="pl-c1">=</span> <span class="pl-c1">null</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span> 

<span class="pl-k">class</span> <span class="pl-smi">Thing</span> <span class="pl-kos">{</span>
  <span class="pl-k">public</span> <span class="pl-c1">hello</span> <span class="pl-c1">=</span> <span class="pl-c1">null</span><span class="pl-kos">;</span>
  <span class="pl-c">/* impl */</span>
<span class="pl-kos">}</span>

<span class="pl-k">const</span> <span class="pl-smi">IdentifiableThing</span> <span class="pl-c1">=</span> <span class="pl-smi">IdentifiableSubclass</span><span class="pl-kos">(</span><span class="pl-smi">Thing</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">class</span> <span class="pl-smi">ChildThing</span> <span class="pl-k">extends</span> <span class="pl-smi">IdentifiableThing</span> <span class="pl-kos">{</span>

<span class="pl-kos">}</span>

<span class="pl-k">let</span> <span class="pl-s1">child</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">ChildThing</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-s1">child</span><span class="pl-kos">.</span><span class="pl-c1">hello</span><span class="pl-kos">;</span> <span class="pl-c">// TS does not understand that this exists</span>
<span class="pl-s1">child</span><span class="pl-kos">.</span><span class="pl-c1">_id</span><span class="pl-kos">;</span>   <span class="pl-c">// TS understands that this exists</span></pre></div>