Perhaps a bit behind the wave on posting about Typescript, but I wanted to take the time to get as familiar as possible with the language and tools before weighing in. After spending some time with it, I have to say I see no downside to using it in your web applications and I’ve identified the below ways you win by putting Typescript to use in your projects.
No Unlearning Of JavaScript or Learning a New Language
Typescript is a superset of JavaScript which is a unique approach to the problem when compared to something like Coffee Script. This means you can continue to use all you already know about JavaScript and only need to learn what Typescript adds to the language. In the end, all your Typescript compiles down to regular JavaScript which makes debugging much easier.
Familiar OO Concepts
There are some very talented web developers out there. Many have been using JavaScript for a very long time and have learned the idiosyncrasies of the language and how to make it mimic some object oriented behaviors by using closures and the like. Recently, however, Microsoft has been nudging those of us developing with their tools more toward HTML5 and JavaScript. This means that many of us are coming from an OO background and the related concepts are familiar to us. We’re going to be more productive using these concepts.
See the below example taken from the Typescript template default script file.
Typescript Example
- class Greeter {
- element: HTMLElement;
- span: HTMLElement;
- timerToken: number;
-
- constructor (element: HTMLElement) {
- this.element = element;
- this.element.innerText += "The time is: ";
- this.span = document.createElement('span');
- this.element.appendChild(this.span);
- this.span.innerText = new Date().toUTCString();
- }
-
- start() {
- this.timerToken = setInterval(() => this.span.innerText = new Date().toUTCString(), 500);
- }
-
- stop() {
- clearTimeout(this.timerToken);
- }
-
- }
-
- window.onload = () => {
- var el = document.getElementById('content');
- var greeter = new Greeter(el);
- greeter.start();
- };
The class definition is being used in this example and the similarities with an OO language are evident. Note that the class also can contain a constructor. For me, this allows the same code file per class paradigm to be used that I’m familiar with when used in conjunction with the module keyword we’ll look at in a minute. Notice, too, how the start and stop methods are defined. Again, familiar to a C# developer.
Compare the above with the below JavaScript which is the result after compiling.
JavaScript Example
- var Greeter = (function () {
- function Greeter(element) {
- this.element = element;
- this.element.innerText += "The time is: ";
- this.span = document.createElement('span');
- this.element.appendChild(this.span);
- this.span.innerText = new Date().toUTCString();
- }
- Greeter.prototype.start = function () {
- var _this = this;
- this.timerToken = setInterval(function () {
- return _this.span.innerText = new Date().toUTCString();
- }, 500);
- };
- Greeter.prototype.stop = function () {
- clearTimeout(this.timerToken);
- };
- return Greeter;
- })();
- window.onload = function () {
- var el = document.getElementById('content');
- var greeter = new Greeter(el);
- greeter.start();
- };
It’s possible to create a construct in pure JavaScript that behaves the same as the Typescript class, but look at how much more complicated the syntax is. The constructor has been replaced by an inner function and the method definitions make use of the prototype pattern.
ECMAScript 6 Features Today
I have seen negative feedback about Typescript from people who are pushing back on changes to their beloved JavaScript language. Truth is, many of the additions Typescript makes to the language, such as lambdas and modules are already proposed for ECMAScript 6 and Typescript is making them available for developers to use today.
Code Organization
I’ve mentioned the module keyword a couple of times already. This is a powerful construct that allows the developer much more flexibility in how they organize their script files in their projects. Below is an example of defining module and exporting a class form it.
Module with Export
- module Sayings {
- export class Greeter {
- greeting: string;
- constructor (message: string) {
- this.greeting = message;
- }
- greet() {
- return "Hello, " + this.greeting;
- }
- }
- }
- var greeter = new Sayings.Greeter("world");
-
- var button = document.createElement('button')
- button.innerText = "Say Hello"
- button.onclick = function() {
- alert(greeter.greet())
- }
-
- document.body.appendChild(button);
Here, a module called “Sayings” is being defined and a class named “Greeter is being exported from it. This means that we can access the Greeter class by specifying “Sayings.Greeter”. This is an example of what Typescript calls an “internal module”. That is a module that is explicitly defined in the code. A second kind of module is an “external module”. There are modules that are implicitly defined in a separate file and are referred to by the file name. Here is an example from the Typescript documentation.
In File main.ts:
import log = module("log");
log.message("hello");
In File log.ts:
export function message(s: string) {
console.log(s);
}
In the log.ts file, a single function is being exported (made visible outside the module). In main.ts, the file log.ts is being imported as a module and the exported method is being called. When you import an external module, its code is physically copied into the file as an internal module. Note that the log module is being imported by file name. In fact, the module name can contain an absolute or relative path such as “C/myproject/script/logger/log” or “./logger/log” where a path that begins with “.” or “..” is determined to be a relative path. This means that you can organize your source files in a hierarchical folder structure like you would in C# and then import them using the relative path similar to how you would use a namespace.
Better Tooling Support
Intellisense for a dynamic language is hard to do. Since you don’t need to specify a type when declaring a variable, when you the variable name followed by a dot, what should intellisense show you? Over the past few versions of Visual Studio, Microsoft has attempted to populate intellisense in useful ways, but there are so many scenarios where it’s just impossible to make even an educated guess about what members might be on a type. In Typescript, if I enter the following

After typing the dot after the variable name “foo”, there is not attempt to display intellisense. After all, what is foo and what members does it have? However, if I specify a type for the variable such as Typescript allows, I get much more useful tooling.

Not only do I now have intellisense, it also displays the the members of the string type which are what apply in this situation. It isn’t necessary to specify types for everything. The typescript compiler goes to great lengths to try and infer the types in your code where they are not specified. For example, if you assign the result of a function that returns a string to a variable, that variable will be considered a string. Likewise, if I had initialized the foo variable to a value of “”, it would also have been inferred to be a string.
Type Checking at Compile Time
JavaScript does not support runtime type checking and Typescript does not add this. However, at compile time, if the Typescript compiler can determine the type of a variable either because the type was explicitly specified or it was inferred, the use of that variable will be checked. This check occurs one time when your ts files are compiled. You can still shoot yourself in the foot at runtime using the dynamic features of JavaScript, but the type checking the compiler gives you brings you one step closer to bug-free code.
Conclusion
This has not been an attempt to exhaustively cover the features of Typescript but simply a post to point out some of the advantages of using it. I hope to post more about specific features and their use in the near future.