<p dir="auto">Graceful type inference proposal.</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="var o = {
  method() {
    this; // `this` is `o` object
  },
  anon: function () {
    this; // `this` is `o` object
  }
};"><pre class="notranslate"><span class="pl-k">var</span> <span class="pl-s1">o</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
  <span class="pl-en">method</span><span class="pl-kos">(</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-c">// `this` is `o` object</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-en">anon</span>: <span class="pl-k">function</span> <span class="pl-kos">(</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-c">// `this` is `o` object</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span></pre></div>
<h1 dir="auto">Background</h1>
<p dir="auto">We've had a few requests to support this typing (like <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="38618139" data-permission-text="Title is private" data-url="https://github.com/microsoft/TypeScript/issues/229" data-hovercard-type="issue" data-hovercard-url="/microsoft/TypeScript/issues/229/hovercard" href="https://github.com/microsoft/TypeScript/issues/229">#229</a>).  This proposal addresses the use cases for a function 'this' type, a class 'this' type, and a corresponding feature for interfaces.</p>
<h1 dir="auto">Motivating Examples</h1>
<h2 dir="auto">Extension (lightweight mixin)</h2>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="interface Model {
  extend&lt;T&gt;(t: T): &lt;type of containing interface&gt; &amp; T;
}

interface NamedModel extends Model {
  name: string;
}

declare function createNameModel(): NamedModel;

var modelWithNameAndAge = createNamedModel().extend({
  age: 30
});
modelWithNameAndAge.name; //valid
modelWithNameAndAge.age; // valid"><pre class="notranslate"><span class="pl-k">interface</span> <span class="pl-smi">Model</span> <span class="pl-kos">{</span>
  <span class="pl-c1">extend</span><span class="pl-c1">&lt;</span><span class="pl-smi">T</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">t</span>: <span class="pl-smi">T</span><span class="pl-kos">)</span>: <span class="pl-c1">&lt;</span><span class="pl-s1">type</span> <span class="pl-s1">of</span> <span class="pl-s1">containing</span> <span class="pl-smi">interface</span><span class="pl-c1">&gt;</span> <span class="pl-c1">&amp;</span> <span class="pl-smi">T</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">interface</span> <span class="pl-smi">NamedModel</span> <span class="pl-k">extends</span> <span class="pl-smi">Model</span> <span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">declare</span> <span class="pl-k">function</span> <span class="pl-s1">createNameModel</span><span class="pl-kos">(</span><span class="pl-kos">)</span>: <span class="pl-smi">NamedModel</span><span class="pl-kos">;</span>

<span class="pl-k">var</span> <span class="pl-s1">modelWithNameAndAge</span> <span class="pl-c1">=</span> <span class="pl-en">createNamedModel</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">extend</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">age</span>: <span class="pl-c1">30</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-s1">modelWithNameAndAge</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">;</span> <span class="pl-c">//valid</span>
<span class="pl-s1">modelWithNameAndAge</span><span class="pl-kos">.</span><span class="pl-c1">age</span><span class="pl-kos">;</span> <span class="pl-c">// valid</span></pre></div>
<h2 dir="auto">Safe instantiation</h2>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function f() {
  this.x = 3;
}
var g = new f(); // gives type an easy way to check f's body or specify instantiated type"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-en">f</span><span class="pl-kos">(</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">x</span> <span class="pl-c1">=</span> <span class="pl-c1">3</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>
<span class="pl-k">var</span> <span class="pl-s1">g</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-s1">f</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// gives type an easy way to check f's body or specify instantiated type</span></pre></div>
<h2 dir="auto">Safe method invocation</h2>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function f() {
  this.x = 3;
}
var obj = {y: &quot;bar&quot;, f: f};
obj.f(); // can’t easily error"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-en">f</span><span class="pl-kos">(</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">x</span> <span class="pl-c1">=</span> <span class="pl-c1">3</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>
<span class="pl-k">var</span> <span class="pl-s1">obj</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span><span class="pl-c1">y</span>: <span class="pl-s">"bar"</span><span class="pl-kos">,</span> <span class="pl-c1">f</span>: <span class="pl-s1">f</span><span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-s1">obj</span><span class="pl-kos">.</span><span class="pl-en">f</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// can’t easily error</span></pre></div>
<h2 dir="auto">Well-typed fluent APIs (also useful for cloning)</h2>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class Parent {
  setBase(property, value): &lt;whatever the child class is&gt; {
    this._secretSet(property, value);
    return this;
  }
}

class Child extends Parent { 
  name:string;
}

var c = new Child();
console.log(c.setBase(&quot;foo&quot;, 1).setBase(&quot;bar&quot;, 2&quot;).name);  //valid"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">Parent</span> <span class="pl-kos">{</span>
  <span class="pl-c1">setBase</span><span class="pl-kos">(</span><span class="pl-s1">property</span><span class="pl-kos">,</span> <span class="pl-s1">value</span><span class="pl-kos">)</span>: <span class="pl-c1">&lt;</span><span class="pl-smi">whatever</span> <span class="pl-s1">the</span> <span class="pl-s1">child</span> <span class="pl-k">class</span> is<span class="pl-c1">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-c1">this</span><span class="pl-kos">.</span><span class="pl-c1">_secretSet</span><span class="pl-kos">(</span><span class="pl-s1">property</span><span class="pl-kos">,</span> <span class="pl-s1">value</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-c1">return</span> <span class="pl-s1">this</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">Child</span> <span class="pl-k">extends</span> <span class="pl-smi">Parent</span> <span class="pl-kos">{</span> 
  <span class="pl-c1">name</span>:<span class="pl-smi">string</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">var</span> <span class="pl-s1">c</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">Child</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">c</span><span class="pl-kos">.</span><span class="pl-en">setBase</span><span class="pl-kos">(</span><span class="pl-s">"foo"</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">setBase</span><span class="pl-kos">(</span><span class="pl-s">"bar"</span><span class="pl-kos">,</span> <span class="pl-c1">2</span>"<span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">)</span><span class="pl-kos">;</span>  <span class="pl-c">//valid</span></pre></div>
<h1 dir="auto">Design</h1>
<p dir="auto">To support the motivating examples, we introduce a 'this' type.  The 'this' type should follow the intuition of the developer.  When used with classes, 'this' type refers to the type of the class it finds itself in.  With functions, 'this' allows you to further document how the function will be used as a constructor and in what context it can be invoked while in an object.</p>
<h2 dir="auto">Classes and 'this'</h2>
<p dir="auto">A class that uses a 'this' is referring to the containing named class.  In the simplest example:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class C {
  myThis(): this { return this; }
}
var c = new C();
var d = c.myThis();"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">C</span> <span class="pl-kos">{</span>
  <span class="pl-en">myThis</span><span class="pl-kos">(</span><span class="pl-kos">)</span>: this <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>
<span class="pl-k">var</span> <span class="pl-s1">c</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">C</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">var</span> <span class="pl-s1">d</span> <span class="pl-c1">=</span> <span class="pl-s1">c</span><span class="pl-kos">.</span><span class="pl-en">myThis</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">We trivially map the 'this' type in the invocation of myThis() to the C type, giving 'd' type C.</p>
<p dir="auto">The type of 'this' will follow with subclasses.  A subclass sees any 'this' in the type of its base class as its own type.  This allows more a fluent API, as in this example:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class C {
  myThis(): this { return this; }
}
class D extends C {
  name: string;
}
var D = new D();
d.myThis().name = &quot;Joe&quot;; //valid"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">C</span> <span class="pl-kos">{</span>
  <span class="pl-en">myThis</span><span class="pl-kos">(</span><span class="pl-kos">)</span>: this <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>
<span class="pl-k">class</span> <span class="pl-smi">D</span> <span class="pl-k">extends</span> <span class="pl-smi">C</span> <span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>
<span class="pl-k">var</span> <span class="pl-smi">D</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">D</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-s1">d</span><span class="pl-kos">.</span><span class="pl-en">myThis</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-c1">name</span> <span class="pl-c1">=</span> <span class="pl-s">"Joe"</span><span class="pl-kos">;</span> <span class="pl-c">//valid</span></pre></div>
<p dir="auto">For this to work correctly, only 'this' or something that resolves to 'this' can be used.  Something which looks like it should work correctly, but can't work safely is this example:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class C {
  newInstance(): this {
    return new C(); // error, 'this' only works with this expressions
  }
}"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">C</span> <span class="pl-kos">{</span>
  <span class="pl-en">newInstance</span><span class="pl-kos">(</span><span class="pl-kos">)</span>: this <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-k">new</span> <span class="pl-smi">C</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// error, 'this' only works with this expressions</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<h2 dir="auto">Functions and 'this'</h2>
<p dir="auto">Functions gain the ability to talk about the shape of the 'this' pointer that is visible in the function body.  The design here leverages the type variables of the function to describe what the shape of 'this' has:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function f&lt;this extends {x:number}&gt;() {
  this.x = 3;
}"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-en">f</span><span class="pl-c1">&lt;</span><span class="pl-smi">this</span> <span class="pl-k">extends</span> <span class="pl-kos">{</span><span class="pl-c1">x</span>:<span class="pl-smi">number</span><span class="pl-kos">}</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</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">x</span> <span class="pl-c1">=</span> <span class="pl-c1">3</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">This is fairly readable, and we could use syntax coloring/tooling to help signify that the 'this' here is a special type variable that is implied by all functions.</p>
<p dir="auto">Once the type of 'this' is described for functions, we can check the inside of the function body, where this is used:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function f&lt;this extends {x:number}&gt;() {
  this.x = 3;
  this.y = 6; //error: y is not available on this
}"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-en">f</span><span class="pl-c1">&lt;</span><span class="pl-smi">this</span> <span class="pl-k">extends</span> <span class="pl-kos">{</span><span class="pl-c1">x</span>:<span class="pl-smi">number</span><span class="pl-kos">}</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</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">x</span> <span class="pl-c1">=</span> <span class="pl-c1">3</span><span class="pl-kos">;</span>
  <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">y</span> <span class="pl-c1">=</span> <span class="pl-c1">6</span><span class="pl-kos">;</span> <span class="pl-c">//error: y is not available on this</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">We can also check invocation sites:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="var o = {myMethod: f, y: &quot;bob&quot;};
o.myMethod(); //error: o does not match the shape of 'this' for 'myMethod'"><pre class="notranslate"><span class="pl-k">var</span> <span class="pl-s1">o</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span><span class="pl-c1">myMethod</span>: <span class="pl-s1">f</span><span class="pl-kos">,</span> <span class="pl-c1">y</span>: <span class="pl-s">"bob"</span><span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-s1">o</span><span class="pl-kos">.</span><span class="pl-en">myMethod</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">//error: o does not match the shape of 'this' for 'myMethod'</span></pre></div>
<p dir="auto">We may even want to error on the assignment when object is first created instead of the invocation site.</p>
<h2 dir="auto">Interfaces and 'this'</h2>
<p dir="auto">Similarly to classes, interfaces currently lack the the ability for a type to refer to itself.  While an interfaces can refer to itself by name, this limits the ability of interfaces that extend the original interface.  Here, we introduce 'this' as a way for interfaces to do this:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="interface Model {
  clone(): this;
}

interface NamedModel extends Model {
  name: string;
}

var t:NamedModel;
t.clone().name; // valid"><pre class="notranslate"><span class="pl-k">interface</span> <span class="pl-smi">Model</span> <span class="pl-kos">{</span>
  <span class="pl-c1">clone</span><span class="pl-kos">(</span><span class="pl-kos">)</span>: this<span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">interface</span> <span class="pl-smi">NamedModel</span> <span class="pl-k">extends</span> <span class="pl-smi">Model</span> <span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">var</span> <span class="pl-s1">t</span>:<span class="pl-smi">NamedModel</span><span class="pl-kos">;</span>
<span class="pl-s1">t</span><span class="pl-kos">.</span><span class="pl-en">clone</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">;</span> <span class="pl-c">// valid</span></pre></div>
<p dir="auto">For this to work, 'this' refers to the containing named type.  This helps eliminate ambiguities like this:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="interface I {
  obj: { myself: this; name: string };
}"><pre class="notranslate"><span class="pl-k">interface</span> <span class="pl-smi">I</span> <span class="pl-kos">{</span>
  <span class="pl-c1">obj</span>: <span class="pl-kos">{</span> <span class="pl-c1">myself</span>: this<span class="pl-kos">;</span> <span class="pl-c1">name</span>: <span class="pl-smi">string</span> <span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">In this example, 'this' refers to I rather than the object literal type.  It's trivial to refactor the object literal type out of the class so that you can describe a 'this' that instead binds to the object literal itself.</p>
<h1 dir="auto">Motivating examples (Redux)</h1>
<p dir="auto">In this section, we re-write the motivating examples using the proposed functionality.</p>
<h2 dir="auto">Extension (lightweight mixin)</h2>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="interface Model {
  extend&lt;T&gt;(t: T): this &amp; T;
}

interface NamedModel extends Model {
  name: string;
}

declare function createNameModel(): NamedModel;

var modelWithNameAndAge = createNamedModel().extend({
  age: 30
});
modelWithNameAndAge.name; //valid
modelWithNameAndAge.age; // valid"><pre class="notranslate"><span class="pl-k">interface</span> <span class="pl-smi">Model</span> <span class="pl-kos">{</span>
  <span class="pl-c1">extend</span><span class="pl-c1">&lt;</span><span class="pl-smi">T</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">t</span>: <span class="pl-smi">T</span><span class="pl-kos">)</span>: this <span class="pl-c1">&amp;</span> <span class="pl-smi">T</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">interface</span> <span class="pl-smi">NamedModel</span> <span class="pl-k">extends</span> <span class="pl-smi">Model</span> <span class="pl-kos">{</span>
  <span class="pl-c1">name</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">declare</span> <span class="pl-k">function</span> <span class="pl-s1">createNameModel</span><span class="pl-kos">(</span><span class="pl-kos">)</span>: <span class="pl-smi">NamedModel</span><span class="pl-kos">;</span>

<span class="pl-k">var</span> <span class="pl-s1">modelWithNameAndAge</span> <span class="pl-c1">=</span> <span class="pl-en">createNamedModel</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">extend</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">age</span>: <span class="pl-c1">30</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-s1">modelWithNameAndAge</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">;</span> <span class="pl-c">//valid</span>
<span class="pl-s1">modelWithNameAndAge</span><span class="pl-kos">.</span><span class="pl-c1">age</span><span class="pl-kos">;</span> <span class="pl-c">// valid</span></pre></div>
<h2 dir="auto">Safe instantiation</h2>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function f&lt;this extends {x:number}&gt;() {
  this.x = 3;
}
var g = new f(); // gives type an easy way to check f's body or specify instantiated type"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-en">f</span><span class="pl-c1">&lt;</span><span class="pl-smi">this</span> <span class="pl-k">extends</span> <span class="pl-kos">{</span><span class="pl-c1">x</span>:<span class="pl-smi">number</span><span class="pl-kos">}</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</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">x</span> <span class="pl-c1">=</span> <span class="pl-c1">3</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>
<span class="pl-k">var</span> <span class="pl-s1">g</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-s1">f</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// gives type an easy way to check f's body or specify instantiated type</span></pre></div>
<h2 dir="auto">Safe method invocation</h2>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function f&lt;this extends {x: number}&gt;() {
  this.x = 3;
}
var obj = {y: &quot;bar&quot;, f: f};
obj.f(); // error: f can not be invoked on obj, missing {x: number}"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-en">f</span><span class="pl-c1">&lt;</span><span class="pl-smi">this</span> <span class="pl-k">extends</span> <span class="pl-kos">{</span><span class="pl-c1">x</span>: <span class="pl-smi">number</span><span class="pl-kos">}</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</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">x</span> <span class="pl-c1">=</span> <span class="pl-c1">3</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>
<span class="pl-k">var</span> <span class="pl-s1">obj</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span><span class="pl-c1">y</span>: <span class="pl-s">"bar"</span><span class="pl-kos">,</span> <span class="pl-c1">f</span>: <span class="pl-s1">f</span><span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-s1">obj</span><span class="pl-kos">.</span><span class="pl-en">f</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// error: f can not be invoked on obj, missing {x: number}</span></pre></div>
<h2 dir="auto">Well-typed fluent APIs (also useful for cloning)</h2>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class Parent {
  setBase(property, value): this {
    this._secretSet(property, value);
    return this;
  }
}

class Child { 
  name:string;
}

var c = new Child();
console.log(c.setBase(&quot;foo&quot;, 1).setBase(&quot;bar&quot;, 2&quot;).name);  //valid"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">Parent</span> <span class="pl-kos">{</span>
  <span class="pl-en">setBase</span><span class="pl-kos">(</span><span class="pl-s1">property</span><span class="pl-kos">,</span> <span class="pl-s1">value</span><span class="pl-kos">)</span>: this <span class="pl-kos">{</span>
    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">_secretSet</span><span class="pl-kos">(</span><span class="pl-s1">property</span><span class="pl-kos">,</span> <span class="pl-s1">value</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>

<span class="pl-k">class</span> <span class="pl-smi">Child</span> <span class="pl-kos">{</span> 
  <span class="pl-c1">name</span>:<span class="pl-smi">string</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">var</span> <span class="pl-s1">c</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">Child</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">c</span><span class="pl-kos">.</span><span class="pl-en">setBase</span><span class="pl-kos">(</span><span class="pl-s">"foo"</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">setBase</span><span class="pl-kos">(</span><span class="pl-s">"bar"</span><span class="pl-kos">,</span> <span class="pl-c1">2</span>"<span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-c1">name</span><span class="pl-kos">)</span><span class="pl-kos">;</span>  <span class="pl-c">//valid</span></pre></div>