When Microsoft introduced TypeScript – a language for large-scale web application development – at the begin of this month I noticed something strange. Similar to the process of buying a car I started by asking myself questions like: “Does it do this, or that?”, “Can I use it for that?”. But my questions were not random at all. Instead it seemed that my intuition, which guides my curiosity about languages that cross-compile to JavaScript, must use a secret checklist. In this post I will try to verbalize that checklist. Frankly, I want to know myself: What do I find important about a higher level language for developing large-scale web applications?
The Water in Aarhus
One day after Microsoft announced TypeScript, Google’s Dart team posted a warm welcome note. They pointed out that there must be something special about the location of Aarhus in Denmark in regards to languages for large-scale web application development:
It must be something in the water. Gilad Bracha and Lars Bak announced Dart in Aarhus, Denmark about a year ago as a “new programming language for structured web programming”. Yesterday, Anders Hejlsberg, once again in Aarhus, Denmark, announced Microsoft’s new programming language, TypeScript, “a language for application-scale JavaScript development”. Obviously, there’s something about the water in Aarhus that causes language designers to want to tackle the problem of large scale web development.
Google’s Dart team concludes that Dart and TypeScript clearly have the same long-term goals:
A year ago, JavaScript programmers would frequently ask us why we needed a new programming language for the web. We argued that developing large web applications was hard, and that optional static type annotations could help. We also argued that the web needed better tooling support. We think that TypeScript has validated both of these statements. Going forward, I think the Dart project and TypeScript will learn a lot from each other.
Let’s walk over to our neighbor’s house with some pie and welcome them. I would like to get to know TypeScript better!
Does TypeScript have a language spec?
That was actually my first question: Does TypeScript have a language specification? Now, let me reiterate that a language specification is not a tutorial, FAQ, or online help about that language. A good language specification is so detailed that it can be used to implement a compiler. Most language specifications have more in common with insurance policies and the legal fine print of credit card applications. I am one of those weirdos that love reading them. But that’s probably, because I work in the kitchen while others enjoy eating dinner without having to worry about the details of preparing a meal.
Good news is, that TypeScript does have a language specification and it is actually readable and not as dry as Dart’s. What conclusions do I draw from the fact that there is a language spec for TypeScript? It tells me that I am dealing with professionals that are serious about language design. Sadly, Adobe has missed to provide a language specification for ActionScript and for that reason never really made the list of what I consider well-designed programming languages.
Does TypeScript support types?
Yes, TypeScript does support types! Like in Dart type annotations are optional. That means at least you can write clean code that is fully typed if you want to. But how about those sneaky types that are not really types, like Object, “*”, or Array? In a perfect world I would not allow any of those. I am in particular interested in Array, because Arrays turn everything you put into them into untyped Objects. In ActionScript Vectors are therefore a better choice.
First I thought TypeScript didn’t support typed arrays, or vectors. But I was wrong. I wrote up this language spec request, and the friendly folks at Microsoft pointed out that typed arrays are already support in TypeScript:
var arr : number[] = [];
I clearly overlooked that when I was reading the TypeScript language spec.
Does TypeScript allow explicit casts?
I know, casting is a bad thing but sometimes you have to deal with code that wants to cast a bunny to a toaster, or vice versa. In order to cast safely your code has to be able to determine what the instance is made of (with something like ‘instanceof’ or ‘is’) and secondly you need to be able to express your intent of ignoring types (with something like ‘as’) against common sense. A typical example would be:
// (bad but at least safe) JavaScript
function feedBunnyOrToaster(bunnyOrToaster:Object)
{
if( bunnyOrToaster instanceof Toaster )
{
var toaster : Toaster = bunnyOrToaster as Toaster;
toaster.feed(new Bagel());
}
else if( bunnyOrToaster instanceof Bunny )
{
var bunny : Bunny = bunnyOrToaster as Bunny;
bunny.feed(new Carrot());
}
}
I did learn that TypeScript supports ‘instanceof’ for reflexion but I couldn’t find anything specific about cast operators, i.e. ‘as’. So I wrote up a language spec request called Please add support for explicit casts with ‘as’ keyword. The Microsoft folks replied promptly and provided a solution that works for me:
var toaster : Toaster = <Toaster>bunnyOrToaster;
This notation is called “type assertion” and will throw an error if ‘bunnyOrToaster’ is not of type ‘Toaster’. In ActionScript ‘as’ does not throw and simply returns NULL if the types don’t match. But that behavior can easily be emulated by using try/catch. So I am fine with that.
Does TypeScript support inheritance?
Yes, TypeScript does support inheritance. You can define classes which can derive from other classes and may implement interfaces. Digging deeper into the inheritance topic I usually get interested in encapsulation and interfaces.
- Can I encapsulate members and methods in private and public sections? (yes, that’s what I want)
- Is everything public? (bad)
- Can I use protected? (nice to have, but I don’t need it)
- Is ‘class’ a primitive type?
var c : Class = MyClass; var x : MyClass = new c();
A class in TypeScript is a combination of two things: A construct signature and a brand. Brands are unique to each class, so you don’t care about those. Your question then boils down to: what type will be assignment compatible with every class? Consider this:
interface Class { new (args:any): any; }This interface will be assignment compatible with any class because all classes will have a construct signature with one or more arguments that returns something assignment compatible with any. You can limit this further depending on your use case.
Does TypeScript support interfaces?
- Can one class implement multiple interfaces, or only one?
- Can I determine whether an object is an instance of a class that implements an interface?
interface IAnimal { ... }
class Animal implements IAnimal {...}
class Snake extends Animal {...}
class Horse extends Animal {...}
var sam = new Snake();
// works: if( sam instanceof Animal ) alert( "Sam is an Animal" ); // flags an error for 'IAnimal' : if( sam instanceof IAnimal ) alert( "Sam is an Animal" );
Not a bug. Interfaces are purely type information, and TypeScript’s type information is only present at compile time. Instanceof is a runtime feature of JavaScript so has no idea what TypeScript types originally existed.
Identifying the lineage of objects in TypeScript must be done the same way it is done in JavaScript today, such as by setting sentinel values during construction or by examining the structure of the object (eg. if it has a ‘talk’ property it must be an animal). TypeScript could possibly provide a library method to do this for you, but it’s a difficult thing to do right since the type information is not available at all at runtime.
This is a bit disappointing. So TypeScript supports interfaces but you can’t really use them for reflection? In my opinion you can’t offer a feature that extends JavaScript and then not support it in situations for it was designed for with the argument that JavaScript does not support that feature. I admit it’s work, but I have implemented it in my ActionScript to JavaScript cross-compiler. You need to emit a table to the JavaScript code that maps from a class name to its implemented interfaces. At compile time you need to statically analyze whether the right hand side of an ‘instanceof’ expression is an interface. If so, your cross-compiler has to ‘virtualize’ the expression and emit something like “adobe.instanceOf(a,b)” instead of “a instanceof b”. It’s work but it can be done. If even I can do it, Microsoft can certainly do it.
At least, why not making type assertions smarter?
var samIsAnimal;
try
{
var tmp : IAnimal = <IAnimal>sam;
samIsAnimal = true;
}
catch(e:Error)
{
samIsAnimal = false;
}
This might actually already work…
Can I split up my TypeScript project into smaller pieces?
Yes, you can. They call it “modules”. It’s pretty cool especially because Modules are “open ended”, meaning you can add more implementations to pre-existing Modules.

Hello, i’m not really agree with your statement on interface, TypeScript interfaces are just pretty much different than the Java/AS one, but that does not make them a flaw in the language, here IFace are just an helper allowing you to retrieve error at compile time, that make them unusable for reflexion purpose (in fact there is pretty much no reflexion support in TS) but allow some pretty cool syntax for example :
interface MyOptions {
option1:string;
option2:string;
}
function myFunction(option:MyOptions) {}
myFunction({
option1: “hello”,
option2 : “world”
})
That kind of syntaxt is pretty new, make you code more readable and smaller, while letting you retrieving compile time error if you misspell a property name, or try to pass a wrong type in a property.
Hello Francois,
I don’t think there is anything wrong with interfaces. You are right that interfaces are useful in many ways – not only in the context of reflection. I do believe, though, that instanceof interface is an important feature that is missing in TypeScript.
Best,
- Bernd
Yeah, the first time I watched Anders’ video introduction to TS it blows my mind. I never have a good impression with Dart.
What I like a bout TS: static typing, tools support, plays well with JS and existing libraries.
What I like TS team to do more: free plugin for open source IDE (Eclipse, VS express)
Thanks
Yeah the interop library is a little akward, but you have to think about it, The expectation is that Typescript code will always run in a JavaScript VM, but Dart may be running under a JS VM or a Dart VM so the interop library is more so used to deal with JS VM to Dart VM communication.There’s not many clean ways to handle that.
Bernd,
What software is Adobe using internally for object-oriented JavaScript?
Lee Brimelow has a nice video tutorial of TypeScript and it includes coding examples. http://www.leebrimelow.com/why-i-like-typescripts/
What are your thoughts about Intel’s HTML5 Development Environment?
http://html5dev-software.intel.com/
Thank you
Hi Dean,
thanks for pointing out Lee’s video. I agree, it’s a great one.
I can’t speak for every team here at Adobe. But I am recommending the following environment for developing large-scale JavaScript applications:
1. TypeScript Visual Studio 2012 plug-in
http://www.microsoft.com/en-us/download/details.aspx?id=34790
2. Web Essentials for Visual Studio 2012
http://visualstudiogallery.msdn.microsoft.com/07d54d12-7133-4e15-becb-6f451ea3bea6
3. Google Chrome browser
https://www.google.com/intl/en/chrome/browser/
I write most of my JavaScript related code in “strict” TypeScript as it were ActionScript and then cross-compile to JavaScript.
All of my own CSS code goes into LESS (http://lesscss.org) files, which get automatically cross-compiled to CSS by the Web Essentials tool chain.
Now, this might surprise you: I debug in Chrome.
Why? – I found Visual Studio’s debugger too awkward to use when I have to make changes to code and styles at runtime. Chrome is easier to use in my opinion for performing “open heart surgery” while the app is running.
Before TypeScript was introduced in November 2012 I had been supportive of Dart. But in my opinion Dart has become weirder and weirder over the years. You can’t access the DOM directly, everything has to be in an isolate, they removed string plus operators, and expressions that I found intuitive like toInt() suddenly generated warnings ((4/2).toInt() – “warning: use 4 ~/ 2″). On top of all the (what I consider) language weirdness the cross-compiled JavaScript looks still hopelessly inefficient. You might have seen this Google video that is an introduction to Dart where they make fun of Haskell. If I remember correctly they said that Dart aims to become a widely used language – not like Haskell, which has only 35 active developers world-wide. Well, this joke might be soon on Dart. At this point GWT is still a better choice even within the set of Google technologies.
I am placing my bets on TypeScript!
Cheers,
- Bernd