In this article, I’ll be giving you a bit of context on why ES6, ES2015, and TypeScript exist and will provide some concrete examples of key language features to help you make your mind up on what the right solution is for you.
A Brief History of ECMA
What is TypeScript?
At BUILD 2016, Anders Hejlsberg, the inventor of C# and TypeScript, put it aptly: It benefits developers and users to use a transpiler like TypeScript to bridge the compatibility and productivity gap. In March 2015, everyone thought once the state of web JS caught up to the state of the art JS, we wouldn’t need transpilers anymore.
Transpilers like TypeScript, Babel or Traceur aim to close this feature gap. TypeScript outshines the competition from a transpile perspective because while Babel or Traceur are great tools that you can install into your IDE/text editor or build a pipeline, they can be buggy and debugging can be problematic. TypeScript in tandem with CLI tools and Visual Studio Code offers a solid development experience.
Let’s look at some specific ES2015 and TypeScript features below, so you can make up your own mind whether to use ES2015 or TypeScript on your project.
Typings (TypeScript only)
Run the following commands:
$> npm install typings
$> typings install lodash
And then add the following statement to the top of your .js file:
/// <reference path=”typings/modules/lodash/index.d.ts” />
Voila, now you have all lodash functions available to you.
If you had any doubts on how to use a particular function, you get more guidance from the IDE when you open the parenthesis. No need break your workflow and pull up documentation in your browser.
Types (TypeScript only)
Take a simple function that takes a parameter and does some string operations, returning a number.
The code seems simple enough, so why do we need types? Consider a scenario where you’re the author of Foo and you know that someone else will consume Foo or Foo will be used elsewhere in the codebase separated from its definition.
Using the colon syntax, we can restrict what bar can be and what Foo can return.
With this implementation, the consumer of Foo knows that they must provide a string and they will get a number back in return. They’ll get proper code completion or a red squiggly line if they make a mistake. Furthermore, this TypeScript code, when transpiled, looks exactly like the code we originally wrote.
Decorators (TypeScript or planned ES future)
Decorators are heavily utilized by Angular 2 and it is a critical feature that rounds out the type story. Decorators are denoted with the @ syntax and can be attached to classes, methods or parameters to attach metadata or behavior about that class, method or parameter at run time. Angular uses decorators to mark classes as @Component, @Directive, @Pipe or @Injectable so that the framework can validate the kind of code the developer is intending to provide to optimize runtime performance.
Classes (TypeScript or ES2015)
You can define classes in ES2015 and TypeScript. You can write constructors and property getters and setters. In TypeScript class definitions also feed into the type system, so the benefits of using classes are clearer. In addition, utilizing type parameters on class constructors or methods, you can create documentation free, easy to use, framework quality code.
Promises (TypeScript or ES2015)
Promises are available natively in ES2015 and TypeScript. Below is an example of wrapping a function with a callback in a promise. By utilizing promises, we simplify code that needs to be written downstream. Promises can be chained, executed in parallel or can be used to defer execution.
See how connect is being consumed below:
Async/Await (TypeScript or planned ES future)
Async/await picks up, where promises leave us. We can declare any function as async, so long as it is awaiting the result of a promise. In the below example, connect internally implements promises and is returning a promise. When we await connect, behind the scenes the code continues to execute asynchronously, with callbacks and all, however to the developer, especially when debugging, the code seems to execute synchronously.
This is a big deal, in terms of avoiding callback hell and heavily indented code. Another benefit is how previously very complicated error handling scenarios now become dead simple to implement.
When async/await is used at the lowest of your application, it allows you to write the rest of your application in this manner as well, simplifying your overall implementation. Below is an example of how connect is consumed.
ES2015 offers some modern features like classes and promises, but it falls short of fully addressing real world development concerns like avoid callbacks, debugging and error handling challenges brought upon by nested code, and still leaving developers to work with a transpiler to reach the widest audience possible. TypeScript is a remarkable piece of technology, offering a world-class integrated development experience. The free and cross-platform Visual Studio Code editor is the icing on the cake.
What are your thoughts and experience with ES2015 or TypeScript?