; last updated - 14 minutes read

The other day I showed a TypeScript program to our architect. He doesn't like JavaScript, but when he saw my TypeScript program, he was pleasantly surprised. TypeScript looks pretty familiar to Java programmers, making it a good language to get started with client-side programming. Plus, the core feature of TypeScript is types, making development much more fun. I know fans of dynamic types disagree, but wait until you've seen the autocompletion and refactoring features of your editor before you judge. Be that as it may: TypeScript comes with powerful type inference, too, so most of the time you can use it as a dynamically typed language and still benefit from types. If you're still sceptical: hard-core JavaScript may be relieved to learn types are optional.

After a couple of works I'd say that TypeScript is the language of choice for me. In earlier times, I've propagated Dart, which is an even nicer choice as a language. Unfortunately, Dart suffered from needing a virtual machine of its own, and the lacking interoperability with existing JavaScript code. So, it didn't make a bit impact on the market yet, so I prefer a language that compiles natively to JavaScript.

So, I've decided to write a tiny tutorial on TypeScript. It's not an exhaustive step-by-step tutorial. I can't beat the official TypeScript manual, so I won't even try. Instead, I'll give you a short tour-de-force from a Java programmers perspective.

(Almost) 100% compatible to JavaScript

Good news for JavaScript programmers: you're already fluent with TypeScript. You just don't know it yet. Every JavaScript program is a valid TypeScript program. OK, almost every program: there are some corner cases that are incompatible due to type inference.

But before you get too enthusiastic: please adopt the TypeScript style of writing code. While it's technically possible to use prototypes, classes usually look a lot cleaner in TypeScript. The same applies to annotations and lambda expressions: you can replace them with functions if you must, but honestly, that only makes your program look clumsy. The new features of TypeScript may be a thin coating of syntactic sugar. But this thin coating improves the expressiveness and conciseness of your programs tremendously.

For Java programmers, the compatibility to JavaScript is a mixed blessing. You have to relearn many things when you least expect it. For instance, iterating over an array using a for loop looks a bit different than it does in most other programming languages. It resembles the for loop introduced with Java 5, but the loop variable is not the array element, but the index to the array element:

for(var key in array) { console.log(key + ' => ' + array[key]); }

The basics

I take it you're already familiar with programming. Probably you've already seen or written a JavaScript program. So I'll skip the chapter explaining the basic stuff. TypeScript is equipped with all the stuff procedural languages usually have: there are variables, conditional statemenent (if (expression) else , loops (the for loop and the while loop), and expressions are written in a pretty natural way.

TypeScript adds some syntactic sugar to functions and methods. You can define optional parameters and rest parameters, the latter being an unlimited number of optional parameters. The Java guys call the same thing "varargs".

If you're familiar with any other procedural programming language - be it BASIC, Pascal, C/C++, Java or C# - you won't run into many surprises. TypeScript is also an object oriented language with functional additions. That's where things get interesting, so we'll continue with types and classes.

Types

Types are what makes TypeScript attractive to enterprise programmers. Most of the time, the enterprise guys are being mocked because they love overly sophisticated design patterns. The kind of design pattern I tend to call "clumsy" because they hardly ever pay off. On the other hand, the enterprise guys are the folks maintaining programs consisting of 100.000+ lines of code. To do so, you need powerful tools. Dynamic types is not to their liking. That's because dynamic typing makes refactoring difficult, if not impossible, it prevents the editor to show autocomplete suggestions, and dynamically typed compilers have a creepy tendency to tolerate bugs hiding in the code during the test phase. Your customer is going to have fun with those hidden bugs.

A friend of mine even claims that the test-first approach has become so popular because of the lack of types.

TypeScript introduces types, but only as an option. Just omit the type if you prefer dynamic typing, just the way every JavaScript programmer does. However, it offers a powerful type inference system, so I doubt you can really do without types. Consider this example. It's valid in JavaScript, but causes an error in TypeScript:

Actually, it's hard to think of an example where changing a type during runtime makes sense, so I don't consider this an annoying restriction. If you really need to change the type, you're free to define the variable explicitly as Any, or - even better - a common supertype of the types you need.

Type notation

Making types optional has an important consequence: the types are written after the variable (postfix notation):

var pi: number = 3.1415 var helloWorld: String = "Hello world!"

Being a Java programmer, I always have a hard time to wrap my head around it. But after a while, you get used to it. More annoying is the lack of integer types. The only numerical type is number, which is always a floating point number. To my surprise, googling "JavaScript integer rounding error" doesn't show useful result, so rounding errors doesn't seem to be much of an issue inside the JavaScript virtual machine. Obviously it has a couple of tricks up it's sleeve. I wrote a little benchmark to put this to a test. The first computers I ever used (Apple IIe, C64 and others) couldn't even count to ten without floating point errors, so I used that as a test. Along the way, the source code gives you an impression of the general look and feel of a non-object oriented TypeScript program:

floatingPointPrecisionTest() integerPrecisionTest() function integerPrecisionTest(): void { var counter: number = 0 while (counter < 1000000000) { counter = counter + 1 console.log(counter) } console.log("Final result: " + counter) console.log("Error:" + (1000000000 - counter)) } function floatingPointPrecisionTest(): void { var counter: number = 0 while (counter < 100000000) { for (var oneToTen=0; oneToTen<10; oneToTen++) { counter = counter + 0.1 } console.log(counter) } console.log("Final result: " + counter) console.log("Error:" + (100000000 - counter)) }

I ran the integer test up to 100 billion loops without floating point errors. The floating point test starts to show errors after ten additions. That's what I expected: you can't express the number 0.1 without rounding errors in the binary system (much the same way you can express 1/3 as a decimal number). Obviously the TypeScript / JavaScript VM distinguishes internally between floating point numbers and integers, even if it presents you only a single unified data type (number).

Another interesting result of my benchmark was performance. The floating point test of the second tab ran in 2.7 seconds. The integer test took 1.22 seconds on my MacBook running on Google Chrome 45. One billion additions in a couple of seconds - that's impressive. Obviously in 2015 performance is not an excuse to implement business logic on the server (unless you want to target low-power mobile devices).

Object oriented programming with classes

There's little to say about classes. They're there, they work more or less the way they work in Java, even the syntax looks familiar. You'll cope with the differences in virtually no time, I guess. For instance, this is an excerpt of a class of my chess program:

class PieceUtils { public fileName(piece: number): string { if (0 == piece) return "wikimediaimages/empty.png"; var prefix = piece < 0 ? "b_" : "w_"; var pieceName: String; switch (piece) { case 1: pieceName = "pawn"; break; case 2: pieceName = "rook"; break; case 3: pieceName = "knight"; break; case 4: pieceName = "bishop"; break; case 5: pieceName = "queen"; break; case 6: pieceName = "king"; break; } return "wikimediaimages/" + prefix + pieceName + ".png"; } public materialValue(piece: number): number { if (piece == Piece.WHITE_PAWN) return 1000 ... return 0; } }

One thing took me a while to get used to. In TypeScript you must add the keyword this to call a method within the current class. If you don't, you're accessing the global variable and function scope. That's one of the peculiarities inherited from JavaScript.

Interfaces and duck typing

Interfaces are particular interesting in TypeScript. TypeScript allows you to add types to every JavaScript library, even as an afterthought.

That's possible because TypeScript uses structural type inference, also known as duck typing. You know the idea: if you've got something that walks like a duck and quacks like a duck, you'll probably call it a duck - unless you are a biologist who cares about family trees and genetic identity. Java follows the genetic approach: Classes and interfaces are compatible if they have common genes. TypeScript is more flexible. It looks at the structure of the class. If the class has the methods and properties defined in the interface, it's compatible.

This approach make the DefintelyTyped project possible. It provides TypeScript definition files for 900+ JavaScript libraries. It's obvious that the Java approach wouldn't be useful in an environment dominated by JavaScript. JavaScript doesn't know interfaces, so you have to use structural type inference to make interfaces a useful tool.

In TypeScript, interfaces can also contain (public) attributes:

interface ClockInterface { currentTime: Date; setTime(d: Date); } class Clock implements ClockInterface { currentTime: Date; setTime(d: Date) { this.currentTime = d; } constructor(h: number, m: number) { } }

Scopes

By default, every member of a TypeScript class is public. Adding the modifier private hides it from the world outside the class. There's no visibility apart from public (which happens to be the default value) and private.

When you organize your source code into modules, there's a similar concept. You can declare classes you want to export. The other classes are hidden from the world outside the module.

static allows you to share a value betweens different instances of an object. Or to put it in JavaScript language: static stores a value or a method in the prototype, instead of storing it in the object.

Optional getters and setters

TypeScript uses properties much the way C#, Groovy and Scala do. If you define a getter and / or a setter, you can omit the function calls and use the properties as if it were a simple attribute of the object:

class Chessboard { private _check:boolean; get check(): boolean { return this._check } set check(value: boolean) { this._check=value } } var c: Chessboard = new Chessboard() c.check=true console.log(c.check)

Functional programming

Almost needless to say, TypeScript is - like JavaScript - a functional language. Other than JavaScript it hides the functions behinds a nice lambda façade. That's pretty much the same as the Java 8 approach - including target typing and powerful autocomplete suggestions of your editor:

trafficLights: string[] = ["red", "yellow", "green"]; trafficLights.forEach((color) =>{ console.log(color)}) window.onmouseup = (mouseEvent) => { console.log(mouseEvent.button);}

Annotations

Annotations (more precisely: decorators) are a major revolution in the JavaScript world, but if you're coming from the Java world, there's nothing special about them. AngularJS 2.0 shows that annotations are just as useful in the JavaScript world as in the Java world. In an earlier article I claimed that annotations fill a gap created by the lack of lambda expressions. TypeScript knows both, and shows that both annotations and lambdas are valuable tools.

Modules

TypeScript finally fills a large gap of JavaScript. It offers decent support of modules. You can separate your program into different files, collect these files in different namespaces and create a huge package structure. In JavaScript you can emulate this using third-party libraries like require.js. Adding the module structure to the core of the language has many advantages. First of all, it simplifies automatic refactoring. Editor support benefits a lot from modules.

There's a lot more to say about modules. But this is only a "getting started" article, so I'll simply point you to the TypeScript documentation.

Generics

Generics are an important part of TypeScript's crusade to introduce types to JavaScript. I didn't use generic types much myself in TypeScript yet, but they seem to work similarly to their Java counterpart, so I'll leave it at that. Just one observation: TypeScript generics are more flexible. You can use them to define both generic functions and generic classes, and you can optionally pass the type as a parameter to a function. This way, you can disambiguate the corner cases (such as passing null to a function, giving the compiler no cue about which type to use).

Parameters are passed to annotations as Json objects, which makes for a slightly less expressive look than their Java counterpart:

@Component({ selector: 'application' }) @View({ templateUrl: 'ApplicationComponent.html' }) // Component controller class ApplicationComponent { ... }

Wrapping it up

It's hard to find things I dislike about TypeScript, especially when I compare it to JavaScript. Well, at the time of writing, I'm a bit disappointed by the open source editors, but I'm sure that'll improve pretty fast. Other than that, I envision a bright future for TypeScript - or a similar language: the IT industry is always good at creating surprises.

It's astonishing how much clearer, how much more concise TypeScript code looks than native JavaScript code does. Granted, EcmaScript 5 and 6 will introduce many concepts of TypeScript to the JavaScript language, but still, the examples I saw still look a bit confusing - even the ES6 examples. That's even more astonishing when I compare the code bit by bit: more often than not both versions are very similar. Maybe that's because I've got myself accustomed to object oriented languages for so many years. But I think there's more to it than that: JavaScript expresses everything in terms of functions. TypeScript knows dedicated entities for different use cases: Classes, annotations, lambda expressions and functions. I believe this makes it easier to recognize the intention of the original programmer quickly. In other words: there's little difference when you're writing a program, but a huge difference when you're trying to maintain a program written by someone else.

TypeScript is the language of choice for AngularJS 2.0 programmers. But it also pays off to use TypeScript if you're using a different framework, including AngularJS 1.x.


Dig deeper

official TypeScript manual


Comments