<onWebFocus />

Knowledge is only real when shared.

TypeScript Adoption

March 2022

Will type annotations find their way into the browser?

Many programming languages have become very popular despite not having or not requiring type checking. The most prominent example being JavaScript but also others like PHP or Python. Static type checking can catch a lot of errors but also make many things more difficult. Checking types for simple programs or algorithms works very well and might be one of the reasons why mostly typed languages are taught in academia. When developing a website one often just patches together plugins trying to make things work. This is much easier to do without type checking. The code can quickly be compiled and tested in the browser. If it works as expected it doesn't really matter if all the types are matching up. Still, more and more web developers are switching over to TypeScript which allows for gradual adoption and can infer lots of types. TypeScript can prevent many issues during development and makes refactoring much easier.

The Proposal

This month a proposal to add type annotations to JavaScript was submitted. Especially the related blog post has started a discussion about many things related to TypeScript. If the proposal was to be implemented, browsers would add these annotations to their JavaScript engine. Type checking isn't expected to happen in the browser. The goal is just to allow running typed JavaScript without the need for an extra build step, therefore improving developer performance.

The annotations should be independent of the compiler used for checking the types. The thought being that several type checkers could evolve around the proposal. Currently, TypeScript eclipses all other compilers in popularity. Worth mentioning is flow-bin which hasn't gained mainstream adoption and still has some issues and missing features. Unlike TypeScript flow doesn't need it's own file extension and similarly to the proposal type annotations are added to regular JavaScript files. Compilation afterwards simply consists of stripping those types away. TypeScript offers features that are compiled into valid JavaScript.

Build Step going to Disappear?

The proposal's main aim is to get rid of the build step required to run code that has already been statically type checked. Performance wise type checking itself takes longer than compilation to regular JavaScript. Tools like snowpack allow for running code quickly in the browser after changes by avoiding many of the performance heavy build tasks.

JavaScript initially focused on small scripts meant to run in the browser where performance and excellence weren't of any consideration. Browser applications however became increasingly important and so people tried to perfect the language after the fact. JavaScript engines in the browser were tweaked to be as performant as possible. On the developer side an additional compile step was added. This step allowed for the use of new syntax elements like the spread operator and ES Modules. Most of these elements eventually got adopted by browser engines so that the build tools doing this compilation could turn of additional steps one after the other. Feature creep was mostly avoided as for a feature to make it into the browser it had to gain mainstream adoption first which provided a sufficient barrier of entry. A lot of features added to JavaScript engines has been driven by such TC39 proposals.

When looking at other languages that have support for static typing (Java, C++, Swift) they all require a compile step and none of them result in code that includes types. At runtime types are simply ignored, as the check during the compile step will guarantee that everything runs smoothly.

For this proposal to be effective it's not necessary the build step removing the types will always disappear. There is no use in shipping types to users browsers as it only increases the size of the application without adding anything useful. Only when developers are creating development builds just to try out the current code this step makes sense to be skipped and since nothing would be downloaded over the internet it would result in a performance boost overall.

Learnings from ES Modules

With version 12 node started supporting the new ES Modules syntax alonside CommonJS which is what most plugins were written in. Just like TypeScript ES Modules were long before used by web developers to write code. Build tools like webpack allowed the user to write ES Modules while using plugins still written in CommonJS and optionally also outputting the resulting code in CommonJS format.

The transition has taken a notoriously long time and there are still plugin authors out there writing and distributing plugins in CommonJS. Crucial parts of next are still written in CommonJS and therefore causing issues when trying to switch the project configuration to ES Modules although writing it in source files has worked fine for a long time. There aren't any supported node versions out there that don't support ES Modules yet package authors are still vary and don't want to just provide an ES Module version of their package.

Might we be heading into a similar situation with TypeScript? Although, interoperability of TypeScript with untyped plugins usually isn't and issue, just like with ES Modules and CommonJS there might be issues arising and it probably will take a long time until most packages have switched over to TypeScript.

Conclusion about the Proposal

Historically Browsers have supported language features that gained sufficient popularity among developers. Gaining mainstream adoption provided a sufficient barrier so that additional features wouldn't negatively affect the performance of browsers. A lot of the features didn't need browser adoption per se as they could easily be used with an additional build step. Most code developers write today would require about twice as long to compile if none of these features hadn't been adopted by browsers. For people looking at websites, there would be almost no noticeable difference. Assuming this trend will continue and seeing how TypeScript is gaining mainstream adoption it's likely that something like this will be implemented by browsers. As with many other things it will not have any noticeable impact just by itself.

Some Other Gamechangers in the Ecosystem

Adding TypeScript to the browser or elsewhere can be considered to be a fundamental change that would ease the developer workflow. Here are some other changes in the ecosystem with a similar or even bigger impact.

JSX in the Browser

Just like TypeScript JSX currently requires a compilation step before it can be run in the browser. Client-side rendering has gained at least as much adoption as TypeScript. Apart from JSX which is mostly supported by React there are similar ways to write HTML syntax inside JavaScript files for Angular and Vue. Unfortunately, all of these approaches are somewhat different making it hard to find a common standard that the browser could implement. Running TypeScript code in the browser without also performing client-side rendering that requires a build step will probably remain an edge case. So this can be seen as another important step towards removing parts of the build step.

TypeScript in Node

Without installing any additional dependencies and adding a build step there is no way for node to execute TypeScript code. Among other things deno exists to solve this problem as it supports running JavaScript as well as TypeScript natively. Deno has failed to gain mainstream adoption but many of it's features are likely to land in node once they become popular enough. This process is similar to how many features spearheaded by yarn afterwards landed in npm.

To avoid compatibility issues TypeScript source files always have their own extension .ts / .tsx. Since all JavaScript can also be run through the TypeScript compiler one can imagine TypeScript simply becoming the default way that .js files are run.

Removing the HTML Request Step in the Browser

Already mentioned in the Browser post this idea is similar. Since most webapplications now dyanmically render the HTML on the client through JavaScript it would reduce the need for an additional request to load the index.html by allowing to directly load a JavaScript file that could then generate the HTML dynamically on the client.

Running Compiled JavaScript Code in the Browser

Desktop applications will never be compiled on the user's computer. Users download them in an already compiled format from the internet or the App Store. As mentioned, with JavaScript it is different. When you open a website the source code is downloaded and compiled each time by every user. This obviously has a grave performance impact since compilation just like running the compiled code takes some time. By using WebAssembly it's already possible to run compiled code in the browser. The source language isn't JavaScript but a much more complex language like C++ or Rust and the compiled code has to interoperate with the slower JavaScript API.

This idea would remove the build step in the browser but guaranteeing the requirement for a build step on the developer side. Also, it would add further complexity as depending on the architecture and operating system of the user a different version of the compiled code would have to ship and developers would need access to any supported configuration during build. JavaScript successfully managed to avoid this issue by compiling on the client. Having said that, this idea is unlikely to be implemented anytime soon.