The Road to Angular 2.0 part 3: Types

Intro


I gave a presentation at the GOTO conference in Amsterdam titled: The Road to Angular 2.0. In this presentation, I walked the Road to Angular 2.0 to figure out why Angular 2.0 was so different from 1.x. This series of blogposts is a follow up to that presentation. theroadtoangular4

Types


Last week we looked at ES6, the next version of JavaScript, and how it is going to change the way we write our Angular 2.0 code. However ES6 was not enough for the Angular 2.0 team. They wanted to add types and annotations to JavaScript. So what the Angular team did was create their own language, called AtScript, which compiled down to JavaScript, which included types and annotations. Microsoft was also working on a language with types which transpiles back to ES5. That language is called TypeScript, and has been developed since 2012. The only thing TypeScript missed, according to the Angular 2.0 team, were annotations. So the two teams got together and the Angular team convinced the TypeScript folks to add annotations. Now there was no more need for AtScript, and it was abandoned in favor for TypeScript. Why create your own language when there is already a better alternative?



TypeScript


TypeScript is a superset of JavaScript, this means that all valid ES5 is valid TypeScript code. This means you can copy and paste the JS you write today and paste it in a TypeScript file and it will just work. Of course TypeScript also adds functionality such as types and annotations that do not have an equivalent in JavaScript. Hence not all valid TypeScript is valid JavaScript. Visually TypeScript looks something like this:
TypeScript

TypeScript is a superset of ES5, it wraps ES6, so you can use all ES6 features, and on top of that it adds types and annotations.

Types


In TypeScript you can add static types to JavaScript code. Consider the following example:
function greeter(name: string) : string {
  return "hi there " + name;
}

greeter('Maarten'); // Hi there Maarten

As you can see the type of the 'name' parameter, of the greeter function, is  type string. The return value of the greeter function is a string as well. Trying to give a number to the greeter function results in a type error at runtime:
greeter(10); // error: Argument of type 'number' is not assignable to parameter of type 'string'.

Types are not limited only to primitives, you can also use 'classes' as types:
class Person {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}

var maarten = new Person('Maarten', 26);
var jarno = new Person('Jarno', 55);
var eric = new Person('Eric', 14);

var persons: Array<Person> = [maarten, jarno, eric];

In the above example you can see how the the array named 'persons' only accept objects of type 'Person'. Basically how generics works in C# and Java and other strongly typed languages.

Annotations


One of the reasons for the Angular team to stop working on AtScript is that TypeScript 1.5 promised to include annotations. Lets dive into what annotations can do by looking at some Angular 2.0 code:
import {Component, View} from 'angular2/angular2';

@Component({
  selector: 'person'
})
@View({
  template: `<p>My name: {{ name }}</p>`
})
class PersonComponent {
  name: string;
  friends: Array<string>;

  constructor(name: string) {
    this.name = name;
  }
}

Annotations are always prefixed with the @ symbol. This means that in the code above there are two annotations: @Component and @View. Note that you can also define your own annotations if you want to, @Component and @View are not "built" into TypeScript, they were created by the Angular team. What an annotation does is decorate a class with extra functionality in a very succinct way. With very little code you can add great a great deal of functionality. Lets look at the @Component and @View annotations from the example above to demonstrate this.

@Component


@Component tells Angular how it should recognize a component. In this case that it should recognize a PersonComponent whenever it sees an HTML element called person. So if you have the following code inside of a HTML template:
<person></person>

Angular will instantiate a PersonComponent.

@View


The @View annotation tells Angular what the template for a particular component is. In the case of the code snippet that defined a PersonComponent, the templates is a HTML paragraph (<p>) with a binding to 'name'. Note that you could also put your template in a separate file and use templateUrl to retrieve the template, just like you could do in Angular 1.x.

Benefits of Types


We have now seen some TypeScript in action including static types and annotations. But what makes ‘types’ so great? After all we have been using JavaScript for years without the need for types at all. So why have types at all?

IDE and text editors love types


The more static information you provide an IDE the better it can help you write your code. Static types enable better autocompletion, better refactoring support and better code navigation. For example: when your editor sees you writing a function and it knows that it takes two numbers and returns a string, it can show a popup window with that information:
typescript-typehint

For the TypeScript team this extra productivity gain is very important. They even provide ways to autocomplete code that was not written in TypeScript. They do this by creating files that annotate other open source libraries or frameworks by defining TypeScript interfaces for them. These files have the .d.ts extension, where ts stands for TypeScript and .d. for definition, and can be used to make your life easier. There is even a GitHub repository with high quality .d.ts files: https://github.com/borisyankov/DefinitelyTyped

Types help you show your intent


Types are not only useful for IDEs, you the human programmer has benefit from them as well. Having type information makes it easier to reason about other people’s code, and even your own code three months down the line.

Is TypeScript required?


TypeScript is not required by Angular 2.0 you can still write ES5 or ES6, and even Dart and never use TypeScript at all. Which is also what the official docs at angular.io are saying, in fact they show ES5 examples next to every TypeScript example. That being said I think writing ES5 or ES6 is not going to be feasible, because I think every tutorial on Angular 2.0 is simply going to assume you use TypeScript. So if you insist on using ES5 or ES6, you will constantly have to rewrite TypeScript examples from the web back to ES5 or ES6 yourself.

I think it is best that you bite the bullet and use TypeScript. But since TypeScript is a superset of JavaScript you can choose when to use TypeScript and when to use pure JavaScript. You can mix and match as you please, this is especially handy when migrating from Angular 1.x to 2.0, but more on that in a later blog post.

In what language is Angular 2.0 is written?


Ever wonder why Angular 1.x is called AngularJS and Angular 2.0 is just Angular 2.0 sans the JS? That is because Angular is no longer just a JavaScript framework, instead it supports multiple languages. Angular 2.0 will support: ES6, ES5, TypeScript and Dart. Dart is a Language by Google that was supposed to transplant JavaScript as the scripting language of the browser. Recently Google announced they will not add Dart to Chrome but will transpile Dart to JavaScript instead. So what do they write Angular 2.0 itself in? The answer is in TypeScript, but they have Dart and JS Facades that help compile Angular 2.0 to JS and Dart versions. Here is a infographic from the Angular 2.0 team that shows how that works:
Angular 2.0 pipeline

You can read the graph as follows: Angular 2.0 is programmed in TypeScript (utmost left) and there are two facades one for JavaScript and one for Dart. The purpose of these facades is making it possible to write idiomatic API's for code for both JS and Dart. This means that both languages get Angular's API in a form that is best suited for that language. From there the traceur compiler outputs JavaScript and Dart versions of the framework.

When you write Angular 2.0 in Dart you write your application with Dart, using the Dart Angular API facade. This is what the two yellow 'Dart' blocks represent in the lower part of the graph.

When you choose to write your Angular 2.0 code in JavaScript you can choose between ES5, ES6 and TypeScript. But you will use the JavaScript API for all three of them. This is what the blue 'JS' part in the top part of the graph represents.

One CLI(hopefully) to rule them all


A colleague of mine asked my while he was reviewing this blogpost: "What do I have to do to use TypeScript in Angular 2.0?". Which is a valid question, after all we have seen this complex graphs with all these facades, but we have no idea on how to use it in our projects.

The answer is that there is no answer yet on how to best build an Angular 2.0 project. But there is hope, the Angular team got together with the React team to discus common ground, and in the notes, Igor from the Angular team, discusses the need for a Command Line Interface (CLI). He states that the Angular is building a CLI that will, and I quote:
  1. Scaffold.
  2. Skeleton files
  3. Set up build
  4. Set up testing environment

By "Scaffold" I think Igor means generating entire base Angular projects, and by "Skeleton files" generating very specific files such as unit test, e2e test and services. "Set up build"  probably mean setting up TypeScript, Dart, ES5  or ES6 depending on the language that you choose. "Set up testing environment" means that it will setup karma and protractor for unit and e2e tests.

The Angular 2.0 team took a page from the Ember playbook, because Ember has had CLI for quite some time. The effect of having a CLI which has first class support and is created the Ember team itself, means that every Ember application out there, uses the same infrastructure to build Ember applications. Plus the Ember build system supports plugins, built on top of the 'default' CLI. This makes for a very powerful standardised way to build Ember applications. Having a big community that uses same tools makes these tools better.

From the meeting notes it is clear that the Angular team is working with the Ember guys to kickstart their own CLI:
We’re working with the Ember CLI team who are extracting reusable bits.  Working with Joe from broccoli and reusing those bits. Current changing the Angular build from gulp to broccoli. Working with the NPM team on package management and resolution. The package managers that exist today aren’t good, but NPM is the closest of all of them.

How this CLI will work exactly is currently still unknown, when there is more information available expect an update from me. That being said I think this is the Angular CLI is a very positive development for us, the Angular community..

Want to know more?


TypeScript adds a lot more functionality on top of JavaScript which I have not covered in this blogpost. Here are some TypeScript resources:

Conclusion


TypeScript was included into Angular 2.0 to allow us to statically define types, which help us write more readable code. TypeScript also includes annotations which allows us to write very little code but achieve much. It gives our IDEs type information to help us be more productive by providing better autocompletion.

So even though you are not forced to use TypeScript I definitely recommend that you do.

We've also seen that Angular 2.0 is no longer a pure "JavaScript" framework but that it supports multiple languages: JavaScript (ES6, and ES5), TypeScript and Dart. The new "CLI" will hopefully make it easy to setup Angular 2.0 projects in a way that the whole Angular community can benefit from it.

In previous weeks and this weeks we have been looking at some mechanical changes in Angular. Things that simply change the way we write Angular, next week we are going to look at components, which will change the way we think about Angular.