The new MVC Single Page Application Template included in ASP.NET and Web Tools 2012.2 is a good place to start if you want to learn more about how to write MVC Single Page Applications using JavaScript and Knockout. As we will see, Single Page Applications is an area where TypeScript really shines, still the template included in update 2.2 is not written using TypeScript. Lets fix that!
Background!
As web browsers have become increasingly capable, and JavaScript libraries are providing ever increasingly advanced features easily accessible, we are seeing more and more functions being moved from the server into the browser. Single page applications and variations of the theme has become more and more used when developing web solutions.
All this means that JavaScript is no longer just a few lines of code adding minor features. JavaScript running in the browser is becoming the language to implement clients with features comparable to what we used to only see in native client applications written in object oriented languages such as C#.
As the number and complexity of the features implemented in JavaScript executing in the browser goes up this means that the complexity of the JavaScript will follow. This in turn means that the days when the JavaScript developers could get away with being more relaxed with respect to good coding practices are definitely over. Following best practices and writing well designed, modular and testable code is now just as important when writing JavaScript for the browser as it is when writing server side code.
Increasing complexity also means that activities such as refactoring of the code will be harder. On the server side we have been used to having the luxury of a compiler that will often gently nudge us in the right direction when we code. One example is Michael Feathers “lean on the compiler” from his book Working Effectively with Legacy Code. In JavaScript we have been used to not having a compiler to lean on so we have had to make do without that help.
In the fall last year Microsoft announced TypeScript which is a superset of JavaScript that adds features specifically targeted at making JavaScript better suited for large scale development. TypeScript adds constructs such as modules and classes that helps structuring the code. TypeScript also adds optional static typing to the language, which enables powerful features such as static analysis also for the JavaScript developer.
The Single Page Application Template
John Papa has already described the Microsoft ASP.NET Single Page Apps template in is blog post Inside the ASP.NET Single Page Apps Template, so I will not go into details on that, but a few key points about the JavaScript view-model should be noted. I am only focusing on the JavaScript as this is the only part of the template that will change as we are converting the app into strongly typed TypeScript.
The sample app is a todo-app for creating lists of todo items that can be checked, the diagram below shows the viewmodel that the view is binding to using knockout.
The viewmodel contains a list of TodoLists. Each todolist has a list of todoitems.
The viewmodel contains a list of TodoLists. Each todolist has a list of todoitems.
The viewmodel has methods to add and delete the todolists, the todolists has methods to add and delete items.
The template creates a project where the application specific javascript code is organized into 5 files:
- Todo.viewmodel.js
contains the todoListViewModel - todo.model.js
TodoList and the TodoItem are both located in this file - todo.datacontext.js
The TodoList/TodoItem objects use the methods datacontext module to update the backend on the server - Ajaxlogin.js
Code to wire up eventhandlers for login and user registration - Todo.bindings.js
Custom Knockout binding handlers.
Converting to TypeScript
Prerequisites
- Make sure you have the latest update for Visual Studio 2012 which at the time of writing is Update 2
- Download and install TypeScript version 0.8.3.1
- I also recommend getting the Web Essentials 2012 extension from the Visual Studio gallery
DefinitelyTyped
Allthough our own code will be well defined and strongly typed TypedScript, we will most likely use 3rd party libraries written in plain old JavaScript. But fear not, Boris Yankov has made available declaration files for most popular JavaScript libraries through his GitHub project DefinitelyTyped.
A declaration file is a file containing interface declarations and variable declaration for a JavaScript library. E.g. the JQuery declaration file (jquery.d.ts) declares the variables jQuery and $ in addition to a number of interfaces.
You can also get the declaration files using nuget packages and you can search for them at tsdpm.
The Ajaxlogin file – fixing potential bugs
The ajaxlogin.js file is just some code that is initially executed which wires click and submit events, so it is maybe not as interesting as some of the other files in the app folder. Still there is at least one detail here that is interesting.
By just adding the jquery declaration file in the top of ajaxlogin and telling the compiler that it should treat it as typescript by naming it ajaxlogin.ts we have provided information about what jquery methods we should and should not use. TypeScript immediately tells us that we should not use the error method on the JQueryPromise object returned by post by marking it with a red squiggly.
In addition the Error List will clearly tell us the same.
Admittedly the error() method is only deprecated, but it may be removed altogether from a future version and this potential bug is not easily detected without the help of strong typing. People often correctly argue that you should test your code, but to be honest it may happen to some of us that we don’t always test all fail paths in our code. This problem that effortlessly shows up in TypeScript may easily be missed without it.
We also note that the correct method: fail(), is used in other post calls in the app and this inconsistency within the application is better fixed as soon as possible.
The model
The model classes are implemented in the three files viewmodel.ts, todolist.ts and todoitem.ts.
Viewmodel
The original JavaScript viewmodel implemented the revealing module pattern. The TypeScript version declares methods as public much to the same effect. The most interesting aspect of the TypeScript implementation is the use of TypeScripts arrow functions. The exposed methods of the viewmodel will be called as callbacks from Knockout. When writing a callback function it is important to make sure that the this reference is correct. Arrow functions in the constructor of a TypeScript class is a common technique to ensure that this reference is correct.
Below you will see the constructor and the addTodoList method, that contains the addFailed method which is using the this reference.
constructor(ko: KnockoutStatic, datacontext: Todo.IDatacontext) {
this.todoLists = ko.observableArray();
this.error = ko.observable();
this.addTodoList = () => {
var todoList = datacontext.createTodoList();
todoList.IsEditingListTitle(true);
datacontext.saveNewTodoList(todoList)
.then(addSucceeded, addFailed);
function addSucceeded() {
showTodoList(todoList);
}
var addFailed = () => {
this.error("Save of new TodoList failed");
}
}
When TypeScript sees an arrow function inside the constructor it will automatically create a local variable called _this inside the constructor function referencing this.
TodoList/TodoItem
The JavaScript version realize these two concepts as functions that accepts a JavaScript object. They both make some assumptions of what this JavaScript object looks like, but being weakly typed code this isn’t really declared anywhere. There’s no warnings before runtime should any of the assumptions fail to hold true.
The TypeScript implementation explicitly declares the contract telling TypeScript to check that anyone who creates e.g. a TodoList should pass an object that implements the interface shown below.
export interface TodoListData {
TodoListId: string;
UserId: string;
Title: string;
Todos: TodoItemData[];
}
This means that we can easily see what kind of object we are expected to pass as parameter, and the compiler will help us should we make a mistake.
Custom MVC templates
The 2012.2 Update includes support for creating custom MVC templates. I followed that guide when creating my template. Being able to upload templates to the Visual studio gallery would have been cool, but unfortunately this seems to not be ready yet. Hanselman wrote in February on his post on the 2012.2 Update that this will be available soon. At the time of writing it looks like it is still not quite there. I get the following error message when attempting to upload which I assume is because it is not yet ready:
Your extension type does not match the VSIX type. It should be uploaded as a Tool.
Conclusion
My view on TypeScript is not that it is a different language to JavaScript. I think of it as an improved JavaScript with 100% compatibility with regular JavaScript. In fact several of the TypeScript features are in the Ecmascript version 6 draft specification which has a target date of December 2013 for completion.
In particular I think that the optional typing of parameters and return values of function is really helpful when my application grows a little bit beyond the most trivial. In my view the TypeScript compiler is a valuable tool which provide the first line of defense against bugs, before the unit tests.