André Staltz recently argued that all Javascript libraries should be authored in TypeScript – which turned out to be rather controversial on reddit. I think that a lot of the resistance originates in the expectation that TypeScript is a completely new language that compiles to Javascript, comparable to the likes of CoffeeScript. In this post I’ll try to clear up this misconception.

It’s not a different language?

Of course it does differ from Javascript - not much room for nuance in short and catchy headlines. That said, you could consider the TypeScript compiler to be somewhat like an advanced Javascript linter. You can add it to your build process, and it will tell you when you’re doing something in your code you probably did not mean to do. It differs from a normal linter, however, in that you add instructions to your code that help the compiler help you.

Helping TypeScript help you

Let’s say we’re writing a Javascript utility library that ensures strings are at least of a certain length by padding them with spaces on the left if necessary. Let’s call this utility function leftpad. The code might look something like this:

function leftpad (str, len) {
  str = String(str);

  var i = -1;

  len = len - str.length;

  while (++i < len) {
    str = ' ' + str;
  }

  return str;
}

Typically when publishing a library, you include some documentation on how to use it. In this case, it should mention that the second argument (len) should be a number for this function to work.

But while properly documented code is good, self-documenting code is better. It’s less work to maintain, and cannot get outdated. Since all valid Javascript is also valid TypeScript, the above code already is valid TypeScript. However, we can also extend it as follows:

function leftpad (str, len: number) {
  str = String(str);

  var i = -1;

  len = len - str.length;

  while (++i < len) {
    str = ' ' + str;
  }

  return str;
}

(In case it’s hard to spot the difference: I added :number after the len argument.)

When you feed this code to the TypeScript compiler, it will simply strip away :number. Before doing that, however, it will check the rest of your code, and warn you when you call leftpad with something other than a number for len.

How does TypeScript help your library’s users?

If your library’s users also use TypeScript, your type annotations enable the compiler to warn them when they pass arguments of the wrong type. Note that the user can still write plain Javascript: simply feeding it to the TypeScript compiler will generate the warnings.

Furthermore, if their editor supports reading your library’s type annotations, it can use those to provide better autocompletion features.

Even without requirements on the tools used by your users, TypeScript libraries have an advantage of being able to generate better documentation. In the past, people tried to add type annotations using JSDoc:

/**
 * …
 * @param {number} len
 * …
 */
function leftpad (str, len) {
  // …
}

A significant disadvantage of comments is that they can easily become outdated. With TypeScript, however, your code will fail to compile if the type annotation becomes incorrect. Thus, if you generate your documentation using something like TypeDoc, your documentation will always include up-to-date type information.

So: should all Javascript libraries be authored in TypeScript?

Of course not. André, too, simply needed a catchy headline. However, if you’re writing a Javascript library, already have a build pipeline, and want to provide a great experience to your library’s users, seriously consider adding type annotations in your code. And since TypeScript currently has the largest following, you might as well use that to add them.

License

This work by Vincent Tunru is licensed under a Creative Commons Attribution 4.0 International License.