JavaScript + Types = TypeScript

For people who haven’t used TypeScript, it’s easy to imagine that it might be a bunch of weird, complicated new stuff on top of JavaScript, in addition to types. In reality, TypeScript is just JavaScript plus the smallest possible set of syntax additions required to let you incrementally typecheck your code.

What’s incredible about the TypeScript compiler is that it doesn’t transpile code so much as just strip out type annotations. Debugging is straightforward because each line of TypeScript corresponds to the same line of JavaScript, just without the types.

Here’s an example TypeScript file, and the resulting compiled JavaScript (targeting ES2017):

As you can see, we’re using cutting-edge ES2017 features like async functions, and the syntax is exactly the same across both. The only difference in the TypeScript version is that we declare the fields on the Person class, as well as the type of the arguments to the constructor; these simply disappear in the JavaScript output.

And even these simple annotations quickly begin to pay dividends. For example, using a TypeScript-enabled editor like VS Code gives us detailed information about class properties, just by hovering our mouse over them:

“But I Still Don’t Want to Use TypeScript!”

And that’s totally cool! Glimmer is a library, first and foremost, for writing JavaScript apps. If you don’t want to use TypeScript, you should have the freedom not to.

“That’s what Angular said and look how that turned out.”

OK, I guess this is maybe the elephant in the room. A lot of people’s first exposure to TypeScript was Angular 2. Looking at the Angular website, it’s easy to get the sense that using TypeScript means JavaScript becomes a de facto second-class citizen.

For example, here’s an Angular component in TypeScript:

Here’s the same thing in ES6 JavaScript:

As you can see, the JavaScript version is quite a bit longer than the TypeScript version. So why wouldn’t Glimmer suffer the same fate?

The primary reason is that Angular relies on an experimental TypeScript feature that emits type information in the compiled JavaScript (i.e., emitDecoratorMetadata ). Dependency injection is front and center in Angular, so they (very rationally) decided to use the types you’d write anyway to power the DI system.

I actually think this is a cool example of improving developer ergonomics in Angular by using existing type information, but it does have the unfortunate effect of requiring different, often awkward APIs for people who want to use JavaScript.

Glimmer goes in the other direction. We like that TypeScript is just JavaScript, so the APIs you use in both languages are exactly the same. Because Glimmer is written in TypeScript, you get great autocompletion and type checking out of the box, but there’s no requirement to use TypeScript, and there’s no alternate set of APIs for JavaScript.