Tuesday, April 30, 2013

Why use TypeScript?

TypeScript is a typed superset of JavaScript that compiles to plain JavaScript, and generates "a semantic subset of JavaScript: the subset that makes sense." - Anders Hejlsberg.

How jeezus many bog-awful JavaScript massacres do you have to see in your life before availing of a gilt-edged opportunity to improve?

When I first heard about TypeScript sometime late last year, I couldn't see the point in it. It isn't one of those indispensable technologies where the only choice is which among competing alternatives to choose, like what database you'll use, or source control system, or issue tracker. Ok, issue tracking isn't, strictly-speaking, necessary. And there are certainly places still operating without source control to speak of, so, maybe not the best example there either. And while we're at it you can get by without a database (in the conventional sense). Ok, so nothing is necessary. You generally get them though, right? At least I haven't been successful in avoiding them in the last 5 years or so. But since TypeScript appears to be seriously optional, you've got to ask yourself one question: “Do I know enough about this exciting new language to make the right decision about whether to use it or not?” Well, do you, punk?

Just ask Anders

Alright, so why does the great Anders Hejlsberg think we need TypeScript? "JavaScript has gone through explosive growth over the last 5 years or so. The fact remains that writing application-scale JavaScript is hard. It was never designed to be a programming language for big applications. It lacks some of the structuring mechanisms you need like classes, modules, and perhaps, interfaces." Not to mention static-typing.

In any case, the idea of using a JavaScript generator isn't new - people were already using Google's GWT or Script#, but apparently (I haven't used either) those frameworks are very different to the JavaScript that they generate. "You were always at arms length from the JavaScript". These quotes incidentally are from the introductory Channel 9 video I wrote about in my post "Getting Started with TypeScript".

I don't know about your circles, but in mine we pay attention to Anders. Despite my skepticism I made myself watch the video, and was pretty much converted straight away. I had just finished reading “Javascript Patterns” by Stoyan Stefanov and was full of the Joys of Pattern, so I recognised a good idea in TypeScript when I saw one. Here was something that was going to whip up some elegant yet solid code, that to me looked familiar from Stefanov's book. Working with TypeScript would be like having +Addy Osmani on your team. Working pro bono, mind!

A linguistic digression

If you're into languages, you can really appreciate the beauty of a native idiom. Occasionally I participate in a French Conversation group whose members meet on Saturday mornings pour bavarder un peu. There's a natural tendency to use flat, word-for-word swaps for phrases or words you don't know, such as the time I was chatting to a guy there and he kept saying "basicament, je..." as in "basically, I...". If you know French, you'll know that you can get lucky turning English adverbs into French ones by sticking a "-ment" at the end, like professionnellement or linguistiquement. But a more idiomatic French way of saying "basically", to my ears at least, is au fond, "at bottom", which I subsequently found. In fact I can't find basicament in my French dictionary of choice. What's all this got to do with JavaScript? Not much to be honest. In fact, I'm surprised you're still reading. What is this, French class?

But seriously, apart from the aesthetics of the matter, writing idiomatic JavaScript is important. Why? Well, it's a bit like using patterns - for example, apart from being the accepted technique for newing up classes and especially derived classes, using the Factory pattern and using the actual word "factory" to name your classes sends a clear message to other devs as to your intention. We're all part of the same culture.

And so if you have to do something difficult in JavaScript like create an inheritance chain, by doing it using TypeScript you can signal your intent very clearly. You can still do this outside of TypeScript (because obviously it just compiles to JavaScript that ultimately is independent of its progenitor code) but it's hard to see what's happening unless you're Stoyan Stefanov, or at least someone familiar with the ways to simulate inheritance in JavaScript. I've read the book: inheritance in JavaScript is not that straightforward, and you don't often see it for that reason. With TypeScript pumping out beautiful idioms from easy to understand keywords and constructs, your JavaScript flows like it's always been your lingua franca, ta langue maternelle.
class Derived extends Base {
    // Derived-specific stuff goes here
Stating your intention explicitly is especially important when it comes to private members, since there is no intrinsic way to provide private properties in JavaScript, whereas you can do so easily in TypeScript, all the time generating idiomatic JavaScript. You can emulate private methods using closures, it's true but again, why not let TypeScript do the dishes?

Shannon River, Limerick 1
'Shannon River, Limerick 1', by HKJen

Type inference flows, flows like the mighty Shannon.

One of the most useful things about TypeScript is its type inference capability; normally, once you go a few levels down into methods, it's hard to see what type (string, function, bool) some variable is supposed to be, calling as it does this method, which chains to that function. It's implicitly, or passively, obfuscated. Type inference is where TypeScript infers (if you haven't already explicitly stated it) from your code what the variable types are. And if anything, in the other direction it's even more useful. That's where if, for example, you create a strongly-typed interface for an object because you'd like to know, at compile time please, whether you mistyped or left out any of the property names on the object. On its own, JavaScript sure isn't going to tell you.

Can't you do all that stuff in JavaScript anyway?

On its own writing JavaScript in Visual Studio isn't going to gives you a warning at development time if you make a mistake; you'll just get a broken app at run time. But assuming no mistakes, yes, you can write clean, idiomatic JavaScript manually of course, but let's be honest here: you rarely see it. Sure, once you realise where TypeScript slots in on the stack you realise that it isn't actually enabling something that wasn't already possible in a good old .js file using crappy ol' good ol' hand-rolled ol' JavaScript like our fathers wrote, and their fathers before them. Meanwhile, in the real world, where the pedestrian and convenient trumps the heroic and possible every time, people (yes, even decent, hardworking devs like you and I) put off using constructs in JavaScript that are routine in C# like namespaces, interfaces, method overloads, and indeed classes despite being possible (at least in their effect) in JavaScript. Why? Because they're hard to achieve, and that's enough to stop people doing them.

So, yes, one can do all the things manually that TypeScript gives you automatically. For example, you can simulate inheritance and have code snippets on standby whenever you want to create an object that derives from a base object. But it'd just be boilerplate code, there's hardly any expressive potential there, so why not automate the ugly (in JavaScript terms) business of inheritance and just let TypeScript do that for you? Function overloading is another pretty tricky aspect of programming in JavaScript: in fact it's not really supported out of the box. To achieve 'overload resolution’ you'd just have to resort to silly pseudo-overloads with slight variations in the name just to get around that limitation, which is no way to live your life at all.

How much is that framework in the window

So, for me at least, the decision to adopt TypeScript into the project was made about 6 months ago, but what would its cost be? Integrating a new framework, or language - whatever you want to call it - into your workflow, into your app, can be expensive, so the question is: how dear is it to integrate TypeScript? Well, naturally, you have to install the TypeScript plug-in, that's the first step. Despite the fact that it's not necessary you'll also want to get Web Essentials, which you have already, right, because how else do you do any LESS?. So, we’re not going to count that. And then, yes, you'll have to learn TypeScript. But it's an extremely shallow learning curve, believe me, so the cost of learning it is de minimis. By my calculation, we have totted up barely any cost so far. Let's keep going. Oh wait, that's it.

Things to come

Have you ever heard the phrase about how the future is already here, it's just not evenly distributed? Truly some walk among us who already live there. Be one of them. Modules are a good example of language changes coming in ECMAScript 6, so by using TypeScript you're getting a headstart, apart from the fact that again, you save yourself handwriting a lot of boilerplate code. Likewise, TypeScript classes are aligned with the ECMAScript 6 proposal for classes, and indeed everything in TypeScript is following the moving ECMAScript 6 standard, so that there's good enough reason to consider a move to TypeScript.

Forget the future

But if I'm realistic - and God knows I try to be - I chose to use TypeScript because of the help it would give me right now, not in some distant future scenario. It has frequently amazed me (each time a little less so) when working with plenty of fine developers to notice how little respect, attention, indeed love, is afforded the JavaScript layer of an app by people who would be aghast to see an MVC controller action out of place for example, or a duplicated call to to a method in the service layer, or a slightly inefficient use of SQL, and so on. Things are inexorably changing for the better, but nowhere near quickly enough, and the impression I get from a lot of senior developers is of otherwise very houseproud people showing you around their new place, check out the kitchen tiles, look at the new deck out the back, ensuite in the master bedroom of course; but the first place you see, the hallway, is a total mess, uncared for, unswept, with shoes and bags strewn over a threadbare carpet. It makes no sense. Forcing yourself to adhere to TypeScript to create your JavaScript and forcing - I mean, persuading by reasoned argument - your team to follow suit, is my recommendation to address the parlous state of your JavaScript layer.