- Type Annotations allow the definition of types and interfaces based upon those types to simplify reasoning about an application system.
- Field Annotations are intended to emphasize the definition and structure of classes and types used in an application.
- Metadata Annotations and Type Introspection allow adding additional meaning to parts of an application, which other parts of the application or a framework can reason about.
Getting Started with AtScript
AtScript implementation development is split between two projects:
- The Traceur transpiler, a popular choice of transpiling ES6 code to ES5 targets, has been enhanced to optionally support AtScript’s language extensions.
- Assert.js is an implementation of a runtime type checker which is called by transpiled AtScript code to define and compare types. Assert.js can be swapped with other implementations to support different kinds of type systems.
While the AngularJS team has provided an AtScript Playground repository, it has not been kept in sync with the current state of Traceur and Assert.js. You can find an updated version in our repository here, which also includes instructions to get up and running along with a set of specs for the different enhancements.
Basic Type Usage
The syntax for adding type information to valid ES6 code is derived from a proposed type system for ECMAScript 4. Simply putting a colon and a type after the thing you are annotating is enough:
The code above says that it expects the value being assigned to the variable aNumber to be aNumber. So what happens when we assign something different?
We get an exception - at runtime:
This mechanism is the basis for developing AtScript with type annotations - during development you will not have to backtrack through several layers of code to find out where things went wrong. You are informed immediately if a value does not fit the expectations - or contract - of your application.
You can do something similar when defining function parameters:
Or when defining a function’s return value:
By using type annotations we are essentially able to express a contract for a function. A developer can take a look at a function’s definition and reason about its inputs and outputs. The contract is enforced by checking inputs and outputs at runtime and generating exceptions if an expectation is not met. You can turn off these checks for production builds in order to not degrade performance.
There are a few built-in types in Assert.js: void, any, string, number, boolean.
void is mostly useful for checking that a function does not return anything.. any will literally match anything including undefined.
Using type annotations becomes increasingly interesting once we plug our own types into the system. If we decide to use an ES6 class as a type, the system will check whether a given parameter is an instance of that class.
This is nice, but it may prevent you from using type annotations in places where the expectations for an input are based upon its interface rather than upon its ancestry. E.g. you want to make sure that an input responds to a specific function call. This is where custom types can be of value:
The function passed to the assert.define call is evaluated to check whether the given argument adheres to the type Quackable.
When presenting AtScript at NgConf, it was also stressed that one might want to use structure type checking for validating Ajax Responses. This can be accomplished using a custom type and the assert.structure helper:
You may also want to use generic types. Generic Types allow you to express types that are containers for values of certain types:
Although the implementation of checking such types in Assert.js is not yet finished, we have implemented a version of it in a fork to showcase the feature.
Field Annotations are a nice feature for expressing the type structure of a class. They allow us to use a shorthand for typed getters and setters of specific class fields:
So, should I use this?
AtScript type checking is a welcome extension to the ES6 language. While one could use the Assert.js library on itself to implement type checking manually, having type requirements directly available as a syntax feature should make type declarations effortless while programming and make programs easier to reason about when examining code. The added runtime checks could prove extremely useful while developing in big teams or with multiple teams.
Despite being a promising development and mostly usable, the AtScript type checking implementation is not finished yet. While Traceur seems to have most of the language features in place, Assert.js still needs work to support (more) generic types. So, while it is interesting to experiment with and maybe use for smaller projects we would advise you to wait for AtScript to stabilize until you use it in production code.