<p dir="auto">Sorry for the crap title, I'm not entirely sure what is going on but I think it's a bug. I also think this is somewhat related to <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="113984571" data-permission-text="Title is private" data-url="https://github.com/microsoft/TypeScript/issues/5449" data-hovercard-type="issue" data-hovercard-url="/microsoft/TypeScript/issues/5449/hovercard" href="https://github.com/microsoft/TypeScript/issues/5449">#5449</a> but am unsure.</p>
<p dir="auto">Library Example:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="export interface InstanceConstructor&lt;T extends BaseModel&gt; {
    new(fac: Factory&lt;T&gt;): T;
}

export class Factory&lt;T extends BaseModel&gt; {
    constructor(private cls: InstanceConstructor&lt;T&gt;) {}

    get() {
        return new this.cls(this);
    }
}

export class BaseModel {
    constructor(private fac: Factory&lt;this&gt;) {}

    refresh() {
        // get returns a new instance, but it should be of
        // type Model, not BaseModel.
        return this.fac.get();
    }
}"><pre class="notranslate"><span class="pl-k">export</span> <span class="pl-k">interface</span> <span class="pl-smi">InstanceConstructor</span><span class="pl-c1">&lt;</span><span class="pl-smi">T</span> <span class="pl-k">extends</span> <span class="pl-smi">BaseModel</span><span class="pl-c1">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">new</span><span class="pl-kos">(</span><span class="pl-s1">fac</span>: <span class="pl-smi">Factory</span><span class="pl-kos">&lt;</span><span class="pl-smi">T</span><span class="pl-kos">&gt;</span><span class="pl-kos">)</span>: <span class="pl-smi">T</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">export</span> <span class="pl-k">class</span> <span class="pl-smi">Factory</span><span class="pl-c1">&lt;</span><span class="pl-smi">T</span> <span class="pl-k">extends</span> <span class="pl-smi">BaseModel</span><span class="pl-c1">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-k">private</span> <span class="pl-s1">cls</span>: <span class="pl-smi">InstanceConstructor</span><span class="pl-kos">&lt;</span><span class="pl-smi">T</span><span class="pl-kos">&gt;</span><span class="pl-kos">)</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>

    <span class="pl-en">get</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">return</span> <span class="pl-k">new</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">cls</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

<span class="pl-k">export</span> <span class="pl-k">class</span> <span class="pl-smi">BaseModel</span> <span class="pl-kos">{</span>
    <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-k">private</span> <span class="pl-s1">fac</span>: <span class="pl-smi">Factory</span><span class="pl-kos">&lt;</span>this<span class="pl-kos">&gt;</span><span class="pl-kos">)</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>

    <span class="pl-en">refresh</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-c">// get returns a new instance, but it should be of</span>
        <span class="pl-c">// type Model, not BaseModel.</span>
        <span class="pl-k">return</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">fac</span><span class="pl-kos">.</span><span class="pl-en">get</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">User Code Example:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="export class Model extends BaseModel {
    do() {
        return true;
    }
}

// Kinda sucks that Factory cannot infer the &quot;Model&quot; type
let f = new Factory&lt;Model&gt;(Model);
let a = f.get();

let b = a.refresh();"><pre class="notranslate"><span class="pl-k">export</span> <span class="pl-k">class</span> <span class="pl-smi">Model</span> <span class="pl-k">extends</span> <span class="pl-smi">BaseModel</span> <span class="pl-kos">{</span>
    <span class="pl-en">do</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">return</span> <span class="pl-c1">true</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

<span class="pl-c">// Kinda sucks that Factory cannot infer the "Model" type</span>
<span class="pl-k">let</span> <span class="pl-s1">f</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">Factory</span><span class="pl-kos">&lt;</span><span class="pl-smi">Model</span><span class="pl-kos">&gt;</span><span class="pl-kos">(</span><span class="pl-smi">Model</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">let</span> <span class="pl-s1">a</span> <span class="pl-c1">=</span> <span class="pl-s1">f</span><span class="pl-kos">.</span><span class="pl-en">get</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">let</span> <span class="pl-s1">b</span> <span class="pl-c1">=</span> <span class="pl-s1">a</span><span class="pl-kos">.</span><span class="pl-en">refresh</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">The issue that the compiler complains about is as follows:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="error TS2345: Argument of type 'typeof Model' is not assignable to parameter of type 'InstanceConstructor&lt;Model&gt;'.
  Types of parameters 'api' and 'api' are incompatible.
    Type 'Factory&lt;this&gt;' is not assignable to type 'Factory&lt;Model&gt;'.
      Type 'this' is not assignable to type 'Model'.
        Type 'BaseModel' is not assignable to type 'Model'.
          Property 'do' is missing in type 'BaseModel'."><pre class="notranslate"><code class="notranslate">error TS2345: Argument of type 'typeof Model' is not assignable to parameter of type 'InstanceConstructor&lt;Model&gt;'.
  Types of parameters 'api' and 'api' are incompatible.
    Type 'Factory&lt;this&gt;' is not assignable to type 'Factory&lt;Model&gt;'.
      Type 'this' is not assignable to type 'Model'.
        Type 'BaseModel' is not assignable to type 'Model'.
          Property 'do' is missing in type 'BaseModel'.
</code></pre></div>
<p dir="auto">If I change the extended model to be specific it errors in different way, but same theme.</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="export class Model extends BaseModel {
    constructor(fac: Factory&lt;Model&gt;) {
        super(fac);
    }

    do() {
        return true;
    }
}"><pre class="notranslate"><span class="pl-k">export</span> <span class="pl-k">class</span> <span class="pl-smi">Model</span> <span class="pl-k">extends</span> <span class="pl-smi">BaseModel</span> <span class="pl-kos">{</span>
    <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">fac</span>: <span class="pl-smi">Factory</span><span class="pl-kos">&lt;</span><span class="pl-smi">Model</span><span class="pl-kos">&gt;</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-smi">super</span><span class="pl-kos">(</span><span class="pl-s1">fac</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>

    <span class="pl-en">do</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">return</span> <span class="pl-c1">true</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="error TS2345: Argument of type 'Factory&lt;Model&gt;' is not assignable to parameter of type 'Factory&lt;this&gt;'.
  Type 'Model' is not assignable to type 'this'."><pre class="notranslate"><code class="notranslate">error TS2345: Argument of type 'Factory&lt;Model&gt;' is not assignable to parameter of type 'Factory&lt;this&gt;'.
  Type 'Model' is not assignable to type 'this'.
</code></pre></div>
<p dir="auto">I think the reason is because <code class="notranslate">this</code> isn't being polymorphic in either the template or the constructor. When <code class="notranslate">this</code> is analyzed in the constructor of <code class="notranslate">BaseModel</code> it seems to stick with that context.</p>
<p dir="auto">I initially posted about the use of polymorphic <code class="notranslate">this</code> which was answered by <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/RyanCavanaugh/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/RyanCavanaugh">@RyanCavanaugh</a> <a href="http://stackoverflow.com/questions/33443793/create-a-generic-factory-in-typescript" rel="nofollow">http://stackoverflow.com/questions/33443793/create-a-generic-factory-in-typescript</a></p>
<p dir="auto">This error also appears on generics with <code class="notranslate">this</code> to the <code class="notranslate">super</code> call (which is the real use case).</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class A {
    constructor(bar: this) { }
    foo(bar: this) { }
}

class B extends A {
    constructor() {
        super(this); // Error
        this.foo(this); // Works
    }
}"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">A</span> <span class="pl-kos">{</span>
    <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">bar</span>: this<span class="pl-kos">)</span> <span class="pl-kos">{</span> <span class="pl-kos">}</span>
    <span class="pl-en">foo</span><span class="pl-kos">(</span><span class="pl-s1">bar</span>: this<span class="pl-kos">)</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">B</span> <span class="pl-k">extends</span> <span class="pl-smi">A</span> <span class="pl-kos">{</span>
    <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-smi">super</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// Error</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">foo</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// Works</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>