Maintaining Context in TypeScript classes

TypeScript is generally pretty good at persisting this in functions but there are certain circumstances where you can (either accidentally or deliberately) get a class function to run in the wrong context.

class Example {
  private name = 'class context';

  public printName() {
    console.log(this.name);
  }
}

var example = new Example();
example.printName();
// => 'class context'
example.printName.call({
  name: 'wrong context'
});
// => 'wrong context'

The most common scenario where I have accidentally caused this behaviour is where a function is bound to a click handler in Knockout and is executed in the context of the DOM element instead of the containing class.

In JavaScript you can always use myFunction.bind(this) to force the context but having to do that in the TypeScript constructor feels messy…

class Example {
  private name = 'class context';

  constructor() {
    this.printName = this._printName.bind(this);
  }

  private _printName() {
    console.log(this.name);
  }
}

var example = new Example();

example.printName();
// => 'class context'
example.printName.call({
  name: 'wrong context'
});
// => 'class context'

Thankfully there’s an easy way to get TypeScript to correctly play ball.  Instead of defining the function inline, assign a lambda expression to a public class variable:

class Example {
  private name = 'class context';

  public printName = () => {
    console.log(this.name);
  }
}

var example = new Example();

example.printName();
// => 'class context'
example.printName.call({
  name: 'wrong context'
});
// => 'class context'

JS Bin on jsbin.com

Much neater!