Blog

TypeScript: Application-Scale JavaScript

Alex Ford

Technical Engineer, Forum One

TypeScript is an alternative to JavaScript that advertises itself as being more suitable for application development: “TypeScript offers classes, modules, and interfaces to help you build robust components. These features are available at development time for high-confidence application development, but are compiled into simple JavaScript.”

It accomplishes this not just with class and module syntax, but a type-checker that is able to ensure you are using those classes and modules properly. The TypeScript compiler outputs ordinary JavaScript, meaning it can be used without any special support from browsers or server-side environments like node.js.

Almost any JavaScript you write is valid TypeScript. I say “almost” because TypeScript’s type-checker will prevent you from misusing objects. TypeScript is able to infer a variable’s type from its declaration, so that a statement like var x = 123; flags x as being a number. The static type checker then complains if you try to call methods that don’t exist on the Number prototype or to reassign x to a string or array. That simple guarantee makes it much easier for IDEs to support development with features like auto-completion and argument checking.

TypeScript borrows some features from the upcoming ECMAScript 6 specification, too. There is convenience syntax for day-to-day programming tasks, such as the arrow function, borrowed from CoffeeScript. The arrow function, which looks like this: (foo, bar) => baz, is shorthand notation for (function (foo, bar) { return baz; }).bind(this). This automatically captures the current value of “this” in scope, which is more often than not what you want. The proposal even states “dynamic this binding is an oft-fired footgun.”

TypeScript for Applications

The core strength of TypeScript is its support for proper components. It standardizes the syntactical differences between CommonJS (e.g., in node.js) and AMD (e.g., in RequireJS) by introducing a single import statement, which is converted to either format on compilation. For other libraries, there is a declare keyword to tell the compiler about existing modules and types. Declarations for commonly used libraries are collected under the auspices of DefinitelyTyped.

It also supports the class syntax from ECMAScript 6. Classes support static and member properties and methods, as well as single inheritance. TypeScript adds not only visibility modifiers (i.e., public/private) but also interface implementations to the mix, allowing for additional flexibility. Interfaces are what you would expect if you came from a Java or C# background, but with a few twists: Any object can implement an interface if it has matching properties, and it’s okay to have extra properties. That is:

interface Point {
   x: number;
   y: number;
}
var x: Point = { x: 1, y: 2 };
var y: Point = { x: 1, y: 2, z: 3 };

is completely acceptable with x and y considered compatible.

This added twist makes interfaces ideal for the options idiom, where a function can take an object with a handful of optional properties (example taken from the jQuery UI typings):

interface EffectOptions {
   effect: string;
   easing?: string;
   duration: any;
   complete: Function;
}

Any type — class or interface — can be augmented with parameters, creating generic types. This is how the Array type is handled: It’s defined as Array<T>, requiring that all members are the same type. The handy part about this is that methods and indexed properties on Array reflect that type parameter, making it much safer for the compiler to examine usage of, for example, the forEach method.

In Use at Forum One

The biggest usage of TypeScript here at Forum One has been for our work on the National Association for Educational Progress (NAEP) reports. Earlier reports were built using CoffeeScript, largely due to its excellent compatibility with older-generation JavaScript runtimes. But large projects run into the same issues they do with plain JavaScript: a lack of type-checking often results in unpredictable behavior when you change a class or structure.

As a result, we moved to a Backbone-based architecture. The typings for Backbone parameterize view subclasses over Backbone.Model objects (that is, a view is Backbone.View<TModel extends Backbone.Model>), which makes it immensely helpful to monitor usage of model objects. This even works well with collections. The subclassing functionality is probably handiest. We’ve been able to create views that manage subviews with minimal fuss thanks to the super keyword: we can dispatch to the superclass’ methods.

Of course, it’s not just the NAEP reports that are seeing the light of TypeScript. We’ve been keeping this somewhat quiet, but perhaps it’s finally time to reveal: Proty is being reborn as a web app. Our stack of choice there is AngularJS, which — conveniently enough — also has typings available. The biggest feature of TypeScript when using Angular is the sanity-checking of $scope. The $scope object is available as an IScope interface, but TypeScript won’t let you add arbitrary properties. This forces you to create a subinterface with the desired properties, holding you to a contract of sorts that you won’t step out of line.

The Future

A good blog post by the TypeScript team describes their future work. The language design is slowly aligning with ECMAScript 6, allowing devs to work with a backwards-compatible implementation of the new specification in addition to the type safety offered by TypeScript. Development occurs on GitHub now, with the developers accepting community contributions in the form of both bug reports and pull requests.

Conclusion

Types are good for you! It seems obvious to say, but most web development projects use scripting languages — such as Ruby, PHP, and/or JavaScript — which lack the benefits of static typing. TypeScript’s goal is to reintroduce the concept and show developers that you can have both flexibility and safety in an existing ecosystem. Give types a chance!

Written By

Alex Ford

Technical Engineer, Forum One