<p dir="auto"><strong>TypeScript Version:</strong><br>
1.8.7</p>
<p dir="auto"><strong>Code</strong></p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="'use strict';

class User {
  firstName: string;
  lastName: string;  

  static getInstance() {
    return new this();
  }
}

class StaffUser extends User {  
  position: string;
}

let staffUser = StaffUser.getInstance();

console.log(staffUser.position); // error TS2339: Property 'position' does not exist on type 'User'"><pre class="notranslate"><span class="pl-s">'use strict'</span><span class="pl-kos">;</span>

<span class="pl-k">class</span> <span class="pl-smi">User</span> <span class="pl-kos">{</span>
  <span class="pl-c1">firstName</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
  <span class="pl-c1">lastName</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>  

  <span class="pl-k">static</span> <span class="pl-en">getInstance</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-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">StaffUser</span> <span class="pl-k">extends</span> <span class="pl-smi">User</span> <span class="pl-kos">{</span>  
  <span class="pl-c1">position</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">let</span> <span class="pl-s1">staffUser</span> <span class="pl-c1">=</span> <span class="pl-smi">StaffUser</span><span class="pl-kos">.</span><span class="pl-en">getInstance</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">staffUser</span><span class="pl-kos">.</span><span class="pl-c1">position</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// error TS2339: Property 'position' does not exist on type 'User'</span></pre></div>
<p dir="auto"><strong>Expected behavior:</strong></p>
<p dir="auto"><code class="notranslate">staffUser</code> should be of type <code class="notranslate">StaffUser</code>, not simply <code class="notranslate">User</code>.</p>
<p dir="auto"><strong>Actual behavior:</strong><br>
The compiler doesn't guess that <code class="notranslate">getInstance</code> in <code class="notranslate">StaffUser</code> returns instances of <code class="notranslate">StaffUser</code>.</p>
<p dir="auto">When trying to implement a fairly basic, but polymorphic, active record style model system we run into issues with the type system not respecting <code class="notranslate">this</code> when used in conjunction with a constructor or template/generic.</p>
<p dir="auto">I've posted before about this here, <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="114630380" data-permission-text="Title is private" data-url="https://github.com/microsoft/TypeScript/issues/5493" data-hovercard-type="issue" data-hovercard-url="/microsoft/TypeScript/issues/5493/hovercard" href="https://github.com/microsoft/TypeScript/issues/5493">#5493</a>, and <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="114586216" data-permission-text="Title is private" data-url="https://github.com/microsoft/TypeScript/issues/5492" data-hovercard-type="issue" data-hovercard-url="/microsoft/TypeScript/issues/5492/hovercard" href="https://github.com/microsoft/TypeScript/issues/5492">#5492</a> appears to mention this behavior also.</p>
<p dir="auto">And here is an SO post this that I made:<br>
<a href="http://stackoverflow.com/questions/33443793/create-a-generic-factory-in-typescript-unsolved" rel="nofollow">http://stackoverflow.com/questions/33443793/create-a-generic-factory-in-typescript-unsolved</a></p>
<p dir="auto">I have recycled my example from <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="114630380" data-permission-text="Title is private" data-url="https://github.com/microsoft/TypeScript/issues/5493" data-hovercard-type="issue" data-hovercard-url="/microsoft/TypeScript/issues/5493/hovercard" href="https://github.com/microsoft/TypeScript/issues/5493">#5493</a> into this ticket for further discussion. I wanted an open ticket representing the desire for such a thing and for discussion but the other two are closed.</p>
<p dir="auto">Here is an example that outlines a model <code class="notranslate">Factory</code> which produces models. If you want to customize the <code class="notranslate">BaseModel</code> that comes back from the <code class="notranslate">Factory</code> you should be able to override it. However this fails because <code class="notranslate">this</code> cannot be used in a static member.</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// Typically in a library
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 {
    // NOTE: Does not work....
    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();
    }
}

// Application Code
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();

// b is inferred as any here.
let b = a.refresh();"><pre class="notranslate"><span class="pl-c">// Typically in a library</span>
<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-c">// NOTE: Does not work....</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>

<span class="pl-c">// Application Code</span>
<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-c">// b is inferred as any here.</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">Maybe this issue is silly and there is an easy workaround. I welcome comments regarding how such a pattern can be achieved.</p>