A first encounter with TypeScript

A nice thing with TypeScript is that it is easy to add it to a project in small pieces. Let’s say we like to use TypeScript for our own types, but we like to keep using standard external javascript libraries as they are.

The most samples are using definition files to “typeify” the external libraries. That is probably the best way to roll in the long run, but it does require us to find a ready made, updated d.ts file for the library in question, or to write one ourselves.

Lucklily it is by no means necessary to do that, we can call the plain javascript easily from your own typed code, if we just define the external types as “any”.

A simple client side router using Backbone
This code activates a Backbone client side router to show some data when a user goes to a url, for example #showitem/1

///<reference path='items.ts'/>
declare var Backbone: any;
window.onload = function () {
    var items = new Items();
    var ApplicationRouter = Backbone.Router.extend({
        routes: {
            "showitem/:itemId": "showItem",
        },
        showItem: function (itemId) {
            var item = items.findItem(itemId);
            if (item == null) {
                alert("Missing item");
            }
            else {
                alert("Found item: " + item.name);
            }
        }
    });
    var applicationRouter = new ApplicationRouter();
    Backbone.history.start();
};

Can you spot the typescript syntax? It’s only the first two lines that tells us we’re not in an ordinary javascript file.

The first line is a reference to another TypeScript file, which in this case is a file with a little bit of type goodness (an interface and a class). The reference makes our editor and compiler almost as helpful as we were in a C#-file when we use the types in that file (in this case Items). So we get autocompletion, type tips, warnings on errors and code navigation.

We could get that for our Backbone-objects aswell. But it would require us to find or write a Backbone.d.ts file, and we do not like to do that currently. Instead we are simply telling the compiler to handle Backbone as a plain Javascript object with our second line declare var Backbone : any;

With that in place the TypeScript compiler let’s us define our Backbone objects however we like. And it leaves the code untouched.

Our own types

As I mentioned we do like static goodness for our own types, so the items.ts file could look like this:

interface Item {
    id: number;
    name: string;
}

class Items { 
    private _items: Item[];
    constructor () {
        this._items = [        
            {id: 1, name: "first" },
            {id: 2, name: "second" }        
        ];
    }    
    findItem(id:number):Item { 
        var filterOnId = this._items.filter(
            (val) => { return val.id == id; }
        );
        if (filterOnId.length != 0) {
            return filterOnId[0];
        }
        else {
            return null;
        }
    }    
}

The interface, the class, the ()=> for function and the type definitions are obviously TypeScript, other than that the code is ordinary javascript.

Bundle and minify the javascript
The TypeScript compiler compiles each ts file to a separate js file. Wouldn’t it be nice to be able to get a bundled and minified version aswell? Yes thats a job that the Asp Net bundler can do for us.

I have my ts-files in the folder /scripts/app (and the external libraries in /scripts/libs). To bundle and minify them automatically I had to go through the following steps:

1. Install-Package Microsoft.AspNet.Web.Optimization
2. Add a bundler.cs file in _AppStart:

using System.Web;
using System.Web.Optimization;

public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {
        
        bundles.Add(new ScriptBundle("~/scripts/application")
            .Include("~/scripts/app/*.js"));
    }
}

3. Activate the bundler from Global.Asax.cs

        protected void Application_Start(object sender, EventArgs e)
        {
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }

4. Rename my html-file to cshtml and change my static script reference to:

    @Scripts.Render("~/scripts/application")

5. Disable debug in Web.Config when I like to have the code minified. (And simply enable it when I like to go through some javsascript debugging).

Add a type definition file
When we do like to add a type definition file, that could also be done in iterations, to begin with (for our route needs) it could be as simple as:

declare module Backbone {
    export class Router {
        constructor (options? );
        routes: any;
    declare var history: {
            start(): void;    
        }
    }

Saved it as backbone.d.ts and remove the Backbone var and insert a reference instead:
///

Happy coding!

Advertisements

3 thoughts on “A first encounter with TypeScript

  1. Thanks! Solved my problem. I had to declare the any-variable outside any class or function. I have not figured out why I could not declare it inside the class or a method in a class.

    Nice to see another “norrlänning”, btw!

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s