.NET Zone is brought to you in partnership with:

I am developer and technology maniac who is working on Microsoft and PHP technologies. I have ASP.NET MVP title and I hold MCAD, MCSD and MCTS certificates. When I have free time I usually play with new technologies, hack something, read books, participate in communities and speak in events. I am also active blogger and my ASP.NET blog is the place you can find some interesting reading about my discoveries and personal thoughts. Gunnar is a DZone MVB and is not an employee of DZone and has posted 140 posts at DZone. You can read more from them at their website. View Full User Profile

Moving ASP.NET Single Page Application to TypeScript

05.28.2013
| 3109 views |
  • submit to reddit

I just moved ASP.NET Single Page Application out-of-box example to TypeScript. My idea was to try out how TypeScript works and what it means to move existing JavaScript application to it. Here is overview about what I did and what was my experience with my first steps on TypeScript.

Prerequisites

You need the following pieces of software installed on your machine to use my code:

What is TypeScript?

TypeScript is superset of JavaScript that is targeted to building large JavaScript application. It supports type hinting, modules and variable scopes. It is not separate language – every JavaScript application is TypeScript application and vice versa.

TypeScript files are “compiled” to JavaScript when you build your application and all rules given in TypeScript files are checked. Errors are shown as usual compile errors that stop the building process. It is easy to avoid mistakes this way that otherwise maybe hard to find.

TypeScript has more familiar object-oriented syntax but it doesn’t do any magic. It is close to JavaScript and to write it one must know how JavaScript works.

ASP.NET SPA default application

Default SPA project JavaScript filesWhen you create new ASP.NET Single Page Application project it has some files already there that make up the sample application.

Besides Web API controllers that are used to move data between user interface and server there are some JavaScript files under Scripts folder:

  • todo.binding.js – additional Knockout bindings for sample application (clearing textbox when user clicks enter, placeholder text functionality for non-HTML5 browsers etc),
  • todo.datacontext.js – one-class-data-layer that coordinates all data operations,
  • todo.model.js – model for sample application, contains classes used by sample application (take these classes as models and not as browser-side version of domain classes),
  • todo.viewmodel.js – view model for sample application.

Some things I don’t like about these files is the fact that each of these files contains one large function that has classes defined inside it. I would like if code is written more object-oriented way and I don’t keep have to keep in mind the fact that these files are actually one big JavaScript calls.

Moving to TypeScript

I moved JavaScript files mentioned above to TypeScript. The only exception was bindings file as it was simple and straight-forward enough. For other files I made the following steps:

  • create new TypeScript files (I prefer one class per file style),
  • add module definition,
  • port code from current file to TypeScript class,
  • make sure all code that is not part of JavaScript class gets called,
  • add new file to JavaScripts bundle,
  • uncomment code in old file,
  • run application and test.

There are some things I made differently:

  • there is one class per TypeScript file,
  • I added special Application.ts file that contains application initialization code.

I like when class files are clean and doesn’t contain code that starts doing something when loaded. If all initialization code is in same file (Application.ts in my case) then it makes me easier to control how application is initialized and started.

Example class

As an example of TypeScript class let’s take TodoItem.ts from my application:

/// <reference path="DataContext.ts" />
 
declare var ko;
declare var todoApp;
 
module TodoApp {
    export class TodoItem {
        datacontext: TodoApp.DataContext;
        TodoItemId: any;
        Title: any;
        IsDone: any;
        TodoListId: any;
 
        public ErrorMessage: any;
        public save;
 
        constructor(data, datacontext: TodoApp.DataContext) {
            this.datacontext = datacontext;
            data = data || {};
 
 
            // Persisted properties
            this.TodoItemId = data.TodoItemId;
            this.Title = ko.observable(data.Title);
            this.IsDone = ko.observable(data.IsDone);
            this.TodoListId = data.TodoListId;
 
            // Non-persisted properties
            this.ErrorMessage = ko.observable();
 
            var _self = this;
            this.save = function () {
                return todoApp.datacontext.saveChangedTodoItem(_self);
            }
 
            // Auto-save when these properties change
            this.IsDone.subscribe(this.save);
            this.Title.subscribe(this.save);
        }
    }
}

And this is the JavaScript that is generated from TypeScript above:

var TodoApp;
(function (TodoApp) {
    var TodoItem = (function () {
        function TodoItem(data, datacontext) {
            this.datacontext = datacontext;
            data = data || {};
            this.TodoItemId = data.TodoItemId;
            this.Title = ko.observable(data.Title);
            this.IsDone = ko.observable(data.IsDone);
            this.TodoListId = data.TodoListId;
            this.ErrorMessage = ko.observable();
            var _self = this;
            this.save = function () {
                return todoApp.datacontext.saveChangedTodoItem(_self);
            };
            this.IsDone.subscribe(this.save);
            this.Title.subscribe(this.save);
        }
        return TodoItem;
    })();
    TodoApp.TodoItem = TodoItem;
})(TodoApp || (TodoApp = {}));

One thing is miss is some good way to write object-oriented code without using typical self-closure hack to refer to class instance safely in methods.

Configuring bundling

Although your TypeScript files are not downloaded to browser when page loads you have to load JavaScript files that were generated by TypeScript. I’m doing the loading of these files in bundling configuration of my web application. It’s done in BundleConfig.cs file under App_Start folder.

bundles.Add(new ScriptBundle("~/bundles/todo").Include(
        "~/Scripts/app/todo.bindings.js",
        "~/Scripts/app/DataContext.js",
        "~/Scripts/app/TodoItem.js",
        "~/Scripts/app/TodoList.js",
        "~/Scripts/app/TodoListViewModel.js",
        "~/Scripts/app/Application.js"
));

JavaScript files generated by TypeScript are in same folder with TypeScript files and they have same name as TypeScript files.

Conclusion

TypeScript is cool thing and I think it’s very good fit for large JavaScript applications as it helps to detect places in code where things are not used the way that was expected. As TypeScript is superset of JavaScript it is easy to convert between those two and also language rules are almost the same. It wasn’t very hard to convert SPA default application JavaScript to TypeScript and I am sure that over next years we will see JavaScript projects that make heavy use of TypeScript.

Published at DZone with permission of Gunnar Peipman, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)