TypeScript and Knockout: Define Computed Observables

ko.computed() in TypeScript

On my second day of figuring out how to use knockout.js and TypeScript, I came upon computed observables and ran into trouble. As a point of reference, this is a simplified version of how I declared my ViewModel in pure JavaScript:

var SampleViewModel = function () {

var self = this;

self.propertyOne = ko.observable();
self.propertyTwo = ko.observable();
self.propertyThree = ko.computed(function () {
return self.propertyOne() + self.propertyTwo();
});
};

This simple ViewModel has three properties. propertyThree is a computed observable that adds together propertyOne and propertyTwo. Works great. Hooray for me!

You’re Going the Wrong Way

Here was my first attempt at recreating the same ViewModel in TypeScript. Remember: THIS DOESN’T WORK.

declare var ko;

// Module
module MyApp {

// Class
export class SampleViewModel {
// Constructor

propertyOne = ko.observable();
propertyTwo = ko.observable();
propertyThree = ko.computed(() => {
return this.propertyOne() +this.propertyTwo();
});
}
}

But I got this error message:

Keyword ‘this’ cannot be referenced in initializers in a class body, or in super constructor calls

The Right Way

Instead, the TypeScript ViewModel should look like this:

declare var ko;

// Module
module MyApp {

// Class
export class SampleViewModel {

propertyOne = ko.observable();
propertyTwo = ko.observable();
propertyThree: any;

// Constructor
constructor () {
this.propertyThree = ko.computed(() => {
return this.propertyOne() + this.propertyTwo();
});
}
}
}

Note that I declared propertyThree as just a plain object and then defined it inside the constructor. In that definition, I used the new lambda syntax that captures the this reference. If we look at the generated JavaScript, it looks nearly identical:

var MyApp;
(function (MyApp) {
var SampleViewModel = (function () {
function SampleViewModel() {
var _this = this;
this.propertyOne = ko.observable();
this.propertyTwo = ko.observable();
this.propertyThree = ko.computed(function () {
return _this.propertyOne() + _this.propertyTwo();
});
}
return SampleViewModel;
})();
MyApp.SampleViewModel = SampleViewModel;
})(MyApp || (MyApp = {}));

Instead of self, the compiler generates _this, but its the same thing!

I was tipped off while reading through the discussion board on CodePlex. Specifically, the following:

”…the only place you can guarantee that ‘this’ is your instance is within the constructor (if called with new). Thus using the arrow syntax here also ensures you are binding correctly (as does the proxy and bind methods above)” - billti
Did that help? Let me know in the comments!