ECMAScript 6/7 on the JVM with TypeScript and Vert.x

Following the latest release of Vert.x 3.2 I’ve just uploaded a new version of vertx-lang-typescript 1.1.0. The library adds TypeScript support to Vert.x 3. TypeScript is a programming language that compiles to JavaScript. It supports the ECMAScript 6 (ECMAScript 2015, ES6) standard and also a few parts of ECMAScript 7 (ES7) already.

vertx-lang-typescript automatically compiles Vert.x verticles written in TypeScript to JavaScript and executes them on the JVM. The library also provides type definitions for the Vert.x JavaScript API. Use them in your favourite TypeScript editor/IDE to get auto-completion, API documentation and meaningful error messages (see screencast).

The latest release of vertx-lang-typescript supports TypeScript 1.7. I figured it would be a good idea to give you a couple of examples how this new version helps you use ECMAScript 6 and 7 features on the JVM today.

ECMAScript 6/7 and Vert.x

Below you find an example verticle written in TypeScript. Well, I left all the TypeScript-specific parts out. In fact the verticle is valid ECMAScript 6 (except for the last snippet [9] which is ECMAScript 7).

First, follow the vertx-lang-typescript README to install the library and to enable TypeScript in Vert.x. Then extract the type definitions (vertx-lang-typescript-1.1.0-typings.zip) into a new directory. Create a new file named es7verticle.ts in this directory and copy the code below into it. Finally, open your command prompt and execute

vertx run es7verticle.ts

This will run a small HTTP server that listens to requests on port 8080. If you open your browser and go to http://localhost:8080 you will see the following:

So far so good. Now let’s have a look at the code. I numbered the individual ECMAScript features used. Here’s a complete list:

  1. Use an arrow function to create a request handler (ES6)
  2. Block-scoped variables do not pollute your global namespace (ES6)
  3. Specify a default value for a function parameter (ES6)
  4. Use rest parameters to collect multiple parameters in an array (ES6)
  5. Spread the contents of an array to function parameters (ES6)
  6. Iterate over array contents using the for…of loop (ES6)
  7. template strings enable string interpolation and multi-line strings (ES6)
  8. Use classes and inheritance (ES6)
  9. Use the new exponentiation operator as a shortcut for Math.pow() (ES7)
/// <reference path="./vertx-js/vertx.d.ts" />

// arrow functions ********************************************* [1]
vertx.createHttpServer().requestHandler(request => {
  // block-scoped variables (let keyword) ********************** [2]
  let response = request.response();
  response.setChunked(true);

  // default parameter ***************************************** [3]
  function send(msg = "NOOP") {
    response.write(msg);
  }
  send();
  send("\n");

  // rest parameters ******************************************* [4]
  function sendMulti(...messages) {
    messages.forEach(msg => response.write(msg));
  }
  sendMulti("Hello", " ", "World", "\n");

  // spread parameters ***************************************** [5]
  let messages = ["Foo", "Bar", "\n"];
  sendMulti(...messages);

  // for...of loop ********************************************* [6]
  let arr = ["1", "+", "1", "=", "2", "\n"];
  for (let v of arr) {
    send(v);
  }

  // multi-line template strings, string interpolation ********* [7]
  let name = "Elvis";
  send(`${name} lives
`);

  // classes *************************************************** [8]
  class Animal {
    eat() {
      send("Animal is eating\n");
    }
  }

  class Dog extends Animal {
    eat() {
      send("Dog is eating\n");
    }

    walk() {
      send("Dog is walking\n");
    }
  }

  class Bird extends Animal {
    eat() {
      super.eat();
      send("Animal is a bird\n");
    }

    fly() {
      send("Bird is flying\n");
    }
  }

  let dog = new Dog();
  let bird = new Bird();
  dog.eat();
  dog.walk();
  bird.eat();
  bird.fly();

  // exponentiation operator *********************************** [9]
  let i = 5 ** 2;
  send("" + i);
  send("\n");

  response.end();
}).listen(8080);

Conclusion

The example demonstrates very well how you can use ECMAScript 6 (and parts of 7) on the JVM today. In fact, there are a lot more cool ES6 features not included in the example such as constants (const), the property shorthand or method properties.

TypeScript is so much more than just ES6. It actually has a very good static type system that allows you to make compile-time type checks. This is makes it much easier to write large Vert.x applications with many verticles. Personally I really like the support that I get from my IDE when programming TypeScript. Since vertx-lang-typescript comes with type definitions for the Vert.x JavaScript API I get auto-completion and access to the documentation right in the editor. I mostly use Sublime by the way, but I have tested it successfully with Visual Studio Code, Eclipse and Atom.

Unfortunately, the only ES7 feature that you can use at the moment with vertx-lang-typescript is the exponentiation operator. TypeScript 1.7 also supports decorators but this feature is disabled at the moment in vertx-lang-typescript because it is experimental and subject to change. I’ll keep you up to date when new features are introduced.

Alternatives

Vert.x core developer Paulo Lopes recently published a blog post on how to use ES6 with Vert.x. He uses Babel, a compiler that translates ECMAScript 6 to 5.

Although this approach works well it is a bit hard to set up and use for my taste. First, you need to wrap your Vert.x application in a NPM package. Second, in order to run your application, you need to compile it with npm run build and then then call npm start.

I haven’t tested this approach but I suppose the fact that you need to wrap your application in a NPM package doesn’t play well with build tools such as Gradle or Maven that you normally would use for a Java project. Additionally, you need to execute two commands to run your verticle. With vertx-lang-typescript you only need one. vertx-lang-typescript also allows you to embed the TypeScript verticle in a larger Vert.x application and also mix multiple languages in one project.

Finally, the approach based on Babel only supports ECMAScript 6 (2015), although more features from ES7 will surely be introduced in Babel in the future. TypeScript on the other hand gives you much more features such as static typing that you will certainly find useful for any larger project.