<p dir="auto">Suppose I want to make a class with tons of chainable methods, like setters. This works fine.</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="
class Chainable {
  public set1(arg) {
    this.arg1 = arg;
    return this;
  } 

  public set2(arg) {
    this.arg2 = arg;
    return this;
  }

  public set3(arg) {
    this.arg3 = arg;
    return this;
  }
}"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">Chainable</span> <span class="pl-kos">{</span>
  <span class="pl-k">public</span> <span class="pl-en">set1</span><span class="pl-kos">(</span><span class="pl-s1">arg</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">arg1</span> <span class="pl-c1">=</span> <span class="pl-s1">arg</span><span class="pl-kos">;</span>
    <span class="pl-k">return</span> <span class="pl-smi">this</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span> 

  <span class="pl-k">public</span> <span class="pl-en">set2</span><span class="pl-kos">(</span><span class="pl-s1">arg</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">arg2</span> <span class="pl-c1">=</span> <span class="pl-s1">arg</span><span class="pl-kos">;</span>
    <span class="pl-k">return</span> <span class="pl-smi">this</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>

  <span class="pl-k">public</span> <span class="pl-en">set3</span><span class="pl-kos">(</span><span class="pl-s1">arg</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">arg3</span> <span class="pl-c1">=</span> <span class="pl-s1">arg</span><span class="pl-kos">;</span>
    <span class="pl-k">return</span> <span class="pl-smi">this</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">This allows us to create and setup a new Chainable much more concisely than would otherwise be possible.</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="
a = new Chainable().set1(foo).set2(bar).set3(baz);
// vs
a = new Chainable();
a.set1(foo);
a.set2(bar);
a.set3(baz);
"><pre class="notranslate"><span class="pl-s1">a</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">Chainable</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">set1</span><span class="pl-kos">(</span><span class="pl-s1">foo</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">set2</span><span class="pl-kos">(</span><span class="pl-s1">bar</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">set3</span><span class="pl-kos">(</span><span class="pl-s1">baz</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// vs</span>
<span class="pl-s1">a</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">Chainable</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-s1">a</span><span class="pl-kos">.</span><span class="pl-en">set1</span><span class="pl-kos">(</span><span class="pl-s1">foo</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-s1">a</span><span class="pl-kos">.</span><span class="pl-en">set2</span><span class="pl-kos">(</span><span class="pl-s1">bar</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-s1">a</span><span class="pl-kos">.</span><span class="pl-en">set3</span><span class="pl-kos">(</span><span class="pl-s1">baz</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">The problem occurs when we want to extend our Chainable class and maintain the chainability of the function calls.</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class SuperChainable extends Chainable {
  public set4(arg) {
    this.arg4 = arg;
    return this;
  }

  public set5(arg) {
    this.arg5 = arg;
    return this;
  }

  public set6(arg) {
    this.arg6 = arg;
    return this;
  }
}"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">SuperChainable</span> <span class="pl-k">extends</span> <span class="pl-smi">Chainable</span> <span class="pl-kos">{</span>
  <span class="pl-k">public</span> <span class="pl-en">set4</span><span class="pl-kos">(</span><span class="pl-s1">arg</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">arg4</span> <span class="pl-c1">=</span> <span class="pl-s1">arg</span><span class="pl-kos">;</span>
    <span class="pl-k">return</span> <span class="pl-smi">this</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>

  <span class="pl-k">public</span> <span class="pl-en">set5</span><span class="pl-kos">(</span><span class="pl-s1">arg</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">arg5</span> <span class="pl-c1">=</span> <span class="pl-s1">arg</span><span class="pl-kos">;</span>
    <span class="pl-k">return</span> <span class="pl-smi">this</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>

  <span class="pl-k">public</span> <span class="pl-en">set6</span><span class="pl-kos">(</span><span class="pl-s1">arg</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">arg6</span> <span class="pl-c1">=</span> <span class="pl-s1">arg</span><span class="pl-kos">;</span>
    <span class="pl-k">return</span> <span class="pl-smi">this</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="a = new SuperChainable().set4(foo).set1(baz); 
// this is fine, because set4 returns a SuperChainable 

a = new SuperChainable().set1(baz).set4(foo);
// this breaks, because set1 is returning a Chainable, not SuperChainable

var a: SuperChainable;
a = new SuperChainable.set1(baz); // typeError, set1 returns a Chainable, not SuperChainable

"><pre class="notranslate"><span class="pl-s1">a</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">SuperChainable</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">set4</span><span class="pl-kos">(</span><span class="pl-s1">foo</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">set1</span><span class="pl-kos">(</span><span class="pl-s1">baz</span><span class="pl-kos">)</span><span class="pl-kos">;</span> 
<span class="pl-c">// this is fine, because set4 returns a SuperChainable </span>

<span class="pl-s1">a</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">SuperChainable</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">set1</span><span class="pl-kos">(</span><span class="pl-s1">baz</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">set4</span><span class="pl-kos">(</span><span class="pl-s1">foo</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// this breaks, because set1 is returning a Chainable, not SuperChainable</span>

<span class="pl-k">var</span> <span class="pl-s1">a</span>: <span class="pl-smi">SuperChainable</span><span class="pl-kos">;</span>
<span class="pl-s1">a</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">SuperChainable</span><span class="pl-kos">.</span><span class="pl-c1">set1</span><span class="pl-kos">(</span><span class="pl-s1">baz</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// typeError, set1 returns a Chainable, not SuperChainable</span>
</pre></div>
<p dir="auto">There is a workaround, but it is verbose and boiler-platey:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class SuperChainable extends Chainable {
  public set4(arg) {
    this.arg4 = arg;
    return this;
  }

  public set5(arg) {
    this.arg5 = arg;
    return this;
  }

  public set6(arg) {
    this.arg6 = arg;
    return this;
  }

  public set1(arg) {
    super.set1(arg);
    return this;
  }

  public set2(arg) {
    super.set2(arg);
    return this;
  }

  public set3(arg) {
    super.set3(arg);
    return this;
  }
}"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">SuperChainable</span> <span class="pl-k">extends</span> <span class="pl-smi">Chainable</span> <span class="pl-kos">{</span>
  <span class="pl-k">public</span> <span class="pl-en">set4</span><span class="pl-kos">(</span><span class="pl-s1">arg</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">arg4</span> <span class="pl-c1">=</span> <span class="pl-s1">arg</span><span class="pl-kos">;</span>
    <span class="pl-k">return</span> <span class="pl-smi">this</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>

  <span class="pl-k">public</span> <span class="pl-en">set5</span><span class="pl-kos">(</span><span class="pl-s1">arg</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">arg5</span> <span class="pl-c1">=</span> <span class="pl-s1">arg</span><span class="pl-kos">;</span>
    <span class="pl-k">return</span> <span class="pl-smi">this</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>

  <span class="pl-k">public</span> <span class="pl-en">set6</span><span class="pl-kos">(</span><span class="pl-s1">arg</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">arg6</span> <span class="pl-c1">=</span> <span class="pl-s1">arg</span><span class="pl-kos">;</span>
    <span class="pl-k">return</span> <span class="pl-smi">this</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>

  <span class="pl-k">public</span> <span class="pl-en">set1</span><span class="pl-kos">(</span><span class="pl-s1">arg</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-en">set1</span><span class="pl-kos">(</span><span class="pl-s1">arg</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">return</span> <span class="pl-smi">this</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>

  <span class="pl-k">public</span> <span class="pl-en">set2</span><span class="pl-kos">(</span><span class="pl-s1">arg</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-en">set2</span><span class="pl-kos">(</span><span class="pl-s1">arg</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">return</span> <span class="pl-smi">this</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>

  <span class="pl-k">public</span> <span class="pl-en">set3</span><span class="pl-kos">(</span><span class="pl-s1">arg</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-en">set3</span><span class="pl-kos">(</span><span class="pl-s1">arg</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">return</span> <span class="pl-smi">this</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">When set1 is called on a SuperChainable and returns <code class="notranslate">this</code>, the <code class="notranslate">this</code> really is a SuperChainable and not a Chainable. So it seems to me that the typescript compiler is in error in treating the return value as a Chainable. If this error were fixed, it would be much easier to create inherited objects that support method chaining.</p>
<p dir="auto">(copied over from now-closed issue on codeplex: <a href="https://typescript.codeplex.com/workitem/2332" rel="nofollow">https://typescript.codeplex.com/workitem/2332</a>)</p>
<p dir="auto">The early discussions about generics had this feature outlined, but it never made it into the final version for some reason. Meanwhile, it would be extremely helpful in some cases. The use case that it most dear to my heart is Knockout:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="interface Observable&lt;T&gt; {
   &lt;U&gt;( this: U, value: T ): U;
}

var viewModel = {
   Str: ko.observable( &quot;abc&quot; ),
   Num: ko.observable( 5 )
};

viewModel.Str( &quot;xyz&quot; ).Num( 10 );"><pre class="notranslate"><code class="notranslate">interface Observable&lt;T&gt; {
   &lt;U&gt;( this: U, value: T ): U;
}

var viewModel = {
   Str: ko.observable( "abc" ),
   Num: ko.observable( 5 )
};

viewModel.Str( "xyz" ).Num( 10 );
</code></pre></div>