The JavaScript community consolidates tools and frameworks about as often as Nicholas Cage makes a good movie. I mean, it happens, but it happens so infrequently that you notice when it does.
Which is why I found the Angular team’s decision to switch from their own AtScript language to TypeScript for Angular 2 particularly interesting. The Angular team had been working with the TypeScript team for some time now, but their decision to use TypeScript directly throws a lot of weight behind the TypeScript project.
And Angular isn’t the only project leveraging TypeScript. Completely coincidentally, we at Telerik released our public beta of NativeScript on the exact same day as the Angular team’s announcement. The NativeScript project’s core JavaScript framework and CLI are both written in TypeScript, and NativeScript treats TypeScript application code as a first-class citizen.
TypeScript has benefited from a number of these announcements in the last few months. In fact, a “highly scientific” Google Trends comparison shows that these recent announcements have given TypeScript more internet points than competing compile-to-JavaScript frameworks:
Why TypeScript? Why now?
TypeScript is not the first attempt to build a language to compile to JavaScript; it’s actually late to the party. The ubiquity of JavaScript as a runtime has inspired people from a variety of programming backgrounds to recreate JavaScript as they see fit. The CoffeeScript team actually maintains a ludicrously long list of 250+ languages that compile to JavaScript. That’s right—OVER TWO HUNDRED AND FIFTY LANGUAGES. At this point I think I’m legally obligated to include this very appropriate xkcd comic.
To be fair some of these languages are fly-by-night creations or proof-of-concept implementations that have never really taken off in the wild (I’m looking at you CobolScript). But many of these languages are major engineering efforts with large ecosystems and large corporate backers. So with that in mind, what differentiates TypeScript from the pack? Here are a few things.
Differentiator #1: It’s opt-in
Compile-to-JavaScript frameworks can generally be categorized into two camps: those that build on top of JavaScript and those that abandon JavaScript completely. Most frameworks fall into the latter camp (abandoning JavaScript altogether), but TypeScript chose to build on top of JavaScript, and Microsoft has adamantly defended this approach. Here’s a telling quote from an older blog post that lays out their views:
“Some examples [of compile-to-JavaScript frameworks], like Dart, portend that JavaScript has fundamental flaws and to support these scenarios requires a “clean break” from JavaScript in both syntax and runtime. We disagree with this point of view. We believe that with committee participant focus, the standards runtime can be expanded and the syntactic features necessary to support JavaScript at scale can be built upon the existing JavaScript standard.”
Because TypeScript is a superset of JavaScript, this means you can rename your existing .js files to be .ts files they’ll usually just work. This is a familiar pattern for web developers, as the CSS processors many of us already use (SASS and LESS for example) work the exact same way.
There are a few edge cases where valid JavaScript isn’t valid TypeScript, but those cases are generally easy to detect and fix
TypeScript includes an optional type system, which many JavaScript developers may scoff at as unnecessary, but many server-side developers view as OMG THANK GOODNESS – I NEED MY TYPES. The great thing about TypeScript’s optional type system is the optional part; it means you can use types where they make sense and omit them where they don’t, and each team can decide where that line is for themselves.
For example, the following TypeScript code defines two local variables as numbers and then uses them in a calculation:
In very simple scenarios like this I personally find the types unnecessary, as it’s very clear what you’re using these variables for. In fact, TypeScript will actually automatically infer the types here from the right-hand sides of these two expressions.
However, suppose you refactor this functionality into a function you intend to use across your application (and which is way more complex than this simple example). Such an approach is shown below:
Here the three number declarations tell TypeScript that this function expects two parameters of type number, and that the function will return a number (The : number at the end defines the return type of the function itself). Here the type declarations feel more useful because this function is intended to be a reusable API. Other developers can use these type declarations to learn how to use this function, and having these types can help you maintain your code over time.
TypeScript enforces these type declarations at compile time. That is, if you use this function the wrong way, such as passing two strings rather than two numbers, your build will fail. Here’s what TypeScript’s command-line interface shows when I try to compile calculateArea( "2", 3 ):
This can help with maintenance as every time you change this function’s API, the type-aware compiler can instantly flag all existing uses of the function, so that you don’t have to rely on a find and replace.
Although TypeScript’s opt-in nature is usually associated with its type system, that same design choice applies to everything that TypeScript offers. TypeScript has modules, classes, interfaces, and more, and if you find them valuable you can use them, but if you don’t, you can continue using vanilla JavaScript as you see fit.
TypeScript didn’t pioneer optional types, as Dart and several languages before it have had such a feature, but TypeScript has made a separate smart design decision that Dart didn’t: betting on JavaScript.
Differentiator #2: Commitment to ECMAScript compatibility
TypeScript has consistently committed to supporting the latest ECMAScript features, which is reassuring to JavaScript developers that are concerned about using a language that may diverge from the standard.
For example the latest TypeScript release introduced support for the let and const keywords, as well as support for ES6 template strings. The upcoming 1.5 release touts an impressive list of ES6 features including ES6 modules, destructuring, the spread operator, and more.
The current version of TypeScript still lags behind other use-ES6-today solutions such as Babel and Traceur (see chart below), but the upcoming version 1.5 of TypeScript aims to close that gap considerably.
Current ES6 compatibility from https://kangax.github.io/compat-table/es6.
It’ll be difficult for TypeScript to keep up with the Traceurs and Babels of the world, as those projects’ explicit aim is to support as many new JavaScript features as possible. What differentiates TypeScript is not the sheer number of new APIs it provides, but rather that it’s providing these new JavaScript features in addition to offering the lightweight type system discussed above.
One of main reasons for having this type system is that it makes all sorts of tooling possible that you can’t do with vanilla JavaScript. Let’s take a look at some of it in action.
Differentiator #3: Tooling
One of the biggest complaints of TypeScript has been that its tooling has historically only been available in Microsoft’s own Visual Studio, but this is starting to change. For instance WebStorm recently added TypeScript support, and there’s a relatively new Eclipse plugin as well.
As a Sublime Text user, I was super excited to see TypeScript’s Jonathan Turner demo a new Sublime Text plugin Microsoft has been working on at ng-conf. You can grab that plugin from GitHub to try it for yourself (thanks to @jasssonpet and @robpenner for pointing me in the right direction.). I’m happy to say that it’s a really well done plugin; all the screenshots I show in this article use it.
To see what sort of tooling TypeScript makes possible let’s return to our calculateArea function from before.
Let’s say you try to pass this method a string, for instance calculateArea( "2", 3 );. Because TypeScript knows about the types this method expects, it knows there’s a problem, and it can inform you about it via the tooling. For example here’s what the error looks like in Sublime Text:
Tooling can similarly flag problems when you try to use the function’s return type inappropriately. For instance here’s the error you’ll see if you try to use the calculateArea function’s result as a string:
TypeScript has a number of other features that are out of the scope of this article, but, when you use them the tooling only gets smarter. For example when you create classes TypeScript automatically knows which properties and methods are available:
It can even handle more complex scenarios like class hierarchies:
Perhaps my favorite feature of TypeScript is its declaration files. I’ll let TypeScript’s docs explain the feature in detail, but I like to think of declaration files as a way to enable code completion for external libraries. The DefinitelyTyped GitHub repo contains declarations for hundreds of existing libraries that you can download and use. These declaration files are becoming quite popular, so much so that even some static type checkers like Facebook Flow are considering using them.
As of an example of how to use these, the code below includes the jQuery declaration file for jQuery API code completion.
This code completion is especially helpful for libraries that you’re not already familiar with. In NativeScript, for instance, we provide access to all iOS and Android APIs via JavaScript. It’s really slick, but the problem is I’m not an Android or iOS developer…so I have no idea what APIs exist. But NativeScript provides TypeScript declaration files (see android17.d.ts and ios.d.ts in this repo), and using them has made my life a lot easier. In the gif below I explore the iOS and Android APIs in Sublime Text:
There are far more features than I have time to cover in this article, but these are the major features that I believe differentiates TypeScript from competing compile-to-JavaScript languages. It’s not that TypeScript is the only language with these features — for example, Dart has an optional type system, some other languages have built on top of JavaScript, and plenty of other languages have been written with tooling in mind. For TypeScript it’s the combination of these features that make TypeScript a language worth considering.
Will TypeScript grow?
The Angular announcement has given TypeScript some hype, but the most interesting TypeScript-related question to me is whether that hype will turn into actual large-scale usage. While several compile-to-JavaScript frameworks have gained a following, none have successfully gone mainstream. For instance the oft-cited TIOBE index of programming languages has zero compile-to-JavaScript languages listed in its top 50. CoffeeScript and Dart are both in the 50–100 section, and TypeScript is not on the list.
As further evidence of the lack of mainstream adoption, check out what happens if you add a preprocessor that has gone mainstream, SASS, to the Google Trend graph I showed before.
I find it fascinating that SASS is so much more popular. Five years ago I would’ve argued that people don’t use compile-to-JavaScript frameworks because they don’t want to add a build step to their app, but nowadays the widespread usage of tasks runners such as Grunt and Gulp has made build steps commonplace. The popularity of SASS also shows that front-end developers no longer seem to be concerned with having a build step in their development workflow. So if that’s the case, why are web developers using CSS preprocessors but not JavaScript preprocessors?
You could make the argument that CSS has more perceived shortcomings than JavaScript, thus explaining the increased CSS preprocessor usage, but my anecdotal experience says that’s not true. In my experience there are about as many JavaScript haters as CSS haters, or at the very least that there’s not a great magnitude of difference.
Here’s my theory: since JavaScript, unlike CSS, contains the logic for your app, people have much stronger opinions about how that logic is written. Developers want to write their web code using whatever conventions they’re already familiar with. CoffeeScript has borrowed several Ruby-isms, and has thus been most popular in the Ruby world. TypeScript was started by the same person who wrote C#, and has thus been most popular in the C# world. This fragmentation of opinions and syntaxes has kept any of these preprocessors from bridging multiple communities and truly taking off.
Why TypeScript might be different
I’ll be honest. I’m one of those web developers that has traditionally seen all of these compile-to-JavaScript frameworks as unnecessary. I like to keep my JavaScript pure, as God intended. I’m far more interested in a preprocessor that stays as true to JavaScript as possible (e.g. Babel), than one that introduces types and tooling.
But TypeScript is the first of these preprocessors that I haven’t immediately dismissed. The minimalistic approach that builds on top of JavaScript is surprisingly appealing, and the commitment to staying true to the ECMAScript standard is reassuring. But as a long-time JavaScript developer, I still find myself hesitant to take the plunge. Douglas Crockford actually summarized the way I feel in this older comment about TypeScript:
Microsoft’s TypeScript may be the best of the many JavaScript front ends. It seems to generate the most attractive code. And I think it should take pressure off of the ECMAScript Standard for new features like type declarations and classes. Anders has shown that these can be provided nicely by a preprocessor, so there is no need to change the underlying language.
I think that JavaScript’s loose typing is one of its best features and that type checking is way overrated. TypeScript adds sweetness, but at a price. It is not a price I am willing to pay.
But while I may not be ready to go all in with TypeScript myself, I also realize that those of us in the JavaScript community aren’t necessarily the target audience of these compile-to-JavaScript languages, and I can definitely see TypeScript appealing to a wide spectrum of developers.
Interestingly Crockford has also had nice things to say about CoffeeScript, as has the general JavaScript community, but CoffeeScript has yet to go mainstream. So what what might make TypeScript different? Perhaps Microsoft + Angular.
CoffeeScript has done well in the Ruby community, but has had trouble breaking out of that ecosystem. TypeScript now has the support of Microsoft and Angular, which are both behemoths that bring massive developer communities with them. If TypeScript can manage to take hold in both communities, maybe it can become the first of these compile-to-JavaScript frameworks to go mainstream.
Plus there’s the growing popularity of ES6 to consider. As ES6 gains traction, more and more people are going to be looking for tools that let them use JavaScript’s new features today. TypeScript provides a compelling use-ES6-today solution, and its type system empowers an impressive set of tooling that other use-ES6-today libraries can’t offer. Will that translate into large-scale real-world usage? Time will tell.
TypeScript Resources
I’ve come across a number of good articles and resources in the process of learning TypeScript and writing this article. These resources are listed below:
The TypeScript Handbook
TypeScript Fundamentals on Pluralsight
Jonathan Turner’s talk on TypeScript in Angular from ng-conf
Creating a TypeScript Workflow with Gulp
Header image courtesy of NBphotostream
The post The Rise of TypeScript? appeared first on Telerik Developer Network.