0 comments

Today, the last day of GOTO, I spoke to a number of different people whom I knew might have an opinion on Anders Hejlsberg's new language, TypeScript. Yesterday's post was mainly a "brain dump" of my notes from the talk. Now after having had time to digest what I saw, I thought I'd make a couple of observations.  

Firstly, TypeScript IS JavaScript. It is not a new syntax like CoffeeScript, and it's not an entirely new language that incidentally can be compiled to JavaScript but really wants to replace it completely, like Google's Dart project.

TypeScript, in my mind has two sides to it. Firstly, as Anders spent a lot of time pointing out, it extends JavaScript with static typing. Secondly, it introduces a class-based OO model that will be much more friendly to C# and Java developers than the traditional prototype-based model that JavaScript uses. The static typing system is, as I pointed out in my post from yesterday, applied using a postfix syntax, where types are appended after the name of the variable. Static typing allows the compiler to perform checks of our code to ensure that when I pass parameters in my method calls, they are indeed of the right type. But more importantly, it enables our tools to help us during development. Here's an example of types in action:

function add(a: number, b: number) {
   return a + b;
}

In the above example, the compiler will throw an error if I try to pass in the parameters as strings or any other type than numbers. An added bonus is that the return type can be inferred, since the compiler knows the types that are being dealt with in the method body.

One of the cool things about TypeScript's interface system is that objects don't have to explicitly inherit from the interface. All they need to do is to match the definition to work. For example: 

interface Person {
  firstName: string;
  lastname: string;
}

function Greet(Person person) {
   return "Hello " + person.firstName + " " + person.lastName;
}

Greet({firstName: "John", lastName: "Smith"});

Notice how the object I pass in to the Greet function isn't explicit about what type it is. It merely mimics the structure defined in the interface. This is quite nifty I think.

As I also mentioned in my post from yesterday, TypeScript's type system allows for far better tooling support than we have been accustomed to up till now. Now don't get me wrong, the latest version of Visual Studio (2012) has become extremely good at handling JavaScript. But I think TypeScript will give us far more that what we have today. Statically typed JavaScript will give us far better support for refactoring our code, since the tool will know a lot more about the code up front. Also, IntelliSense (or other intelligent code-completion methods) will be much, much better. 

On the topic of Intellisense, one of the other majorly cool things is the external declaration file system. External declaration files allow us (or third-parties) to provide files that describe the internal structure of a library. This will give us true IntelliSense support for libraries like jQuery and Underscore. When instantiating jQuery, we have 8 different overloads to deal with. When using TypeScript, we will have much better control, since our tools will be able to tell what we're trying to do and thus only display the constructors (or other methods) that make sense at the time. 

The other thing that TypeScript provides us is class-based object orientation, as opposed to prototypal inheritance which can be quite confusing to people coming from the C# or Java worlds. Here's a silly little example that should demonstrate how classes and inheritance works, as well as the resulting JavaScript code.

class Vehicle {
	private numberOfWheels: number;
	constructor(noOfWheels: number) {
		this.numberOfWheels = noOfWheels;
	}
}

class Bycicle extends Vehicle {
	constructor() {
		super(2);
	}
}

And the resulting code: 

var __extends = this.__extends || function (d, b) {
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
}
var Vehicle = (function () {
    function Vehicle(noOfWheels) {
        this.numberOfWheels = noOfWheels;
    }
    return Vehicle;
})();
var Bycicle = (function (_super) {
    __extends(Bycicle, _super);
    function Bycicle() {
        _super.call(this, 2);
    }
    return Bycicle;
})(Vehicle);

Notice the __extends method that gets injected at the top. This is one of the only places where TypeScript injects code to your system that you didn't actually write yourself. It's used for some of the prototype plumbing that is needed to get the JavaScript objects to behave the way we want them to. Now a major advantage here is that the private keyword can be enforced by the compiler and thus help us by hiding inaccessible members. This really isn't possible in JavaScript. Also, as I pointed out yesterday, the class syntax is based on the official ECMAScript 6 proposal, and thus isn't something Microsoft have just pulled out of a magic hat. What this means is that once we get support for ECMAScript 6 (sometime in the distant future), the TypeScript compiler won't have to worry about compiling classes anymore. Neat!

Finally, TypeScript gives us support for JavaScript's module concept: 

module Utils {
	function Util1() {
		return "Hello World"
	}
}
// results in
var Utils;
(function (Utils) {
    function Util1() {
        return "Hello World";
    }
})(Utils || (Utils = {}));

So all in all I am pretty happy about what I see coming in TypeScript. I was pretty skeptical (to say the least) when I heard the announcement that Microsoft and Anders Hejlsberg were going to be giving us something "In the JavaScript tooling space". I must admit that I think TypeScript hits a nice sweet spot without becoming intrusive. I look forward to playing around a bit more with it and seeing how it affects my coding. The fact that TypeScript does a lot of type inference means that I can continue coding JavaScript like I normally do, but my tools and the compiler will be able to do a much better job of helping me out.

comments powered by Disqus