TypeScript to WebAssembly: The What, The How And The Why

Now that you know what WebAssembly is, you understand how you need another language, and WebAssemblyScript is just that: essentially a stricter version of TypeScript (if you can believe that) that can easily be compiled into WASM.

What do I mean by stricter? Well, TypeScript by design has several limitations compared to JavaScript when it comes to types and everything related to them because well, that’s the whole point about it!

However, it still benefits from a lot of the dynamism and flexibility from JavaScript which is hard to efficiently compile ahead of time. Remember that JavaScript is compiled during execution time and we can’t do that here, we need to compile it first, and then execute that output.

So with WebAssemblyScript we can’t do the following things we’re used to with TypeScript:

  • No more any or undefined types. You need to be explicit when it counts, meaning there is some type inference, but you can’t allow for dynamic behavior here.
  • You can’t create type unions (i.e string | number ).
  • Objects need to be strictly typed. Meaning you can’t just create literal objects and start adding properties to them, you have to either use a Map or a proper class with pre-defined types.
  • All modules execute inside a secured sandbox, which means there is no direct access to any external APIs. This is great, until you realized this means no direct DOM access for front-end projects. You have to manually import and exports the functions you want to use or share with the outside world of your module.
  • As of now, the current implementation of WebAssemblyScript only allows for numeric values to be exchanged between your modules and the outside world (i.e the runtime where your code is running). This means strings, arrays and object exchange is out of the question (as of now). They do have workarounds, which are also limited to strings and arrays, but they’re just that: workarounds. The actual solutions are still under development.
  • Closures are not yet implemented. This is a feature they’re pretty much interested in having but considering it’s still not yet implemented, you have to be sure to not use any type of closures in your code. This might be harder said that done, considering how much a part of the language these constructs are.

Their recommendation when it comes to the lack of support for closures, is to implement something like this:

Either use a for loop or move the declaration of sum outside of the computeSum function, like this:

My personal recommendation would be to go for the second option and try to avoid a functional approach as much as possible, that way you’ll stay way from closures.

If you’re still interested in checking out this project, then you’re in luck, because using it is relatively easy.

First of all, you’ll need to have Node installed, because we’re going to be installing a couple of npm packages.

First, create a new project folder, and once inside it, run:

This will initiate your project, it’ll ask a few questions, you can leave the default values for all of them. Then, once that is out of the way, run the following commands:

That will install everything you need to get started, once both commands have finished, you can run:

This will create the required folder structure with all the boilerplate code in place.

As you can see, quite a lot of files and folders are created. With this done, you’ll have to install the new dependencies added to the project with npm install .

This is it, once you’ve installed all new dependencies, you’re actually ready to get started. I know it sounds like a lot of setting up, but that’s it. You can now start adding code inside the assembly folder and once you’re ready to compile it, just run:

And look for the compiled code inside the build folder. A sample code is already included so you can run this command right out of the box and see what it does.

Finally, if you want to test out your compiled code, you can create an index.html file in the root of the project and add the following code to it:

Again, there is a lot of boilerplate code required to just load your WASM code and use it, but think of the power you’re accessing through it. Notice how we’re using the WebAssembly object out of nowhere, this was tested on Chrome and works great, which means this is a native feature of your browsers you’re not using.

After all of this, all the restrictions and all the boilerplate code required, why would you go through all the trouble of writing semi-typescript to then have to load it in such an awkward way?

Well, there are benefits after all, specially to WebAssembly, you have to remember that because you’re compiling the code before execution, you have the following benefits:

  • A degree of security that no dynamic language can give you. If your code compiles, you can be sure it won’t let you crash it due to a problematically typed variable.
  • Reliable optimization. Remember, we’re not dealing with the JIT here, that requires execution time to understand how to optimize your code. Your compiled code will be optimized in the right places, everytime you execute it, no matter what.
  • Performance-wise, if we’re talking about heavy computation code, then it’s much better than JavaScript.

And in particular, if you add on top of all that the fact that you don’t have to learn a completely new language (such as Rust or C) in order to compile it to WASM, WebAssemblyScript starts making total sense. This is a perfect way of bridging the gap for JavaScript developers who’re not used to other languages.

Granted, learning a completely new language has its benefits as well, but if time is not on your side, taking advantage of an already familiar syntax is always great!

So to answer the question, why would you use WebAssemblyScript?, well if you’re dealing with a heavy computation-based problem such as:

  • Video editing
  • Music applications
  • VR-related projects
  • Image recognition
  • Game development (some parts at least)
  • Crypto-related algorithms
  • …etc

Then maybe, WASM and WebAssemblyScript in particular could be a good option.

If on the other hand, you’re dealing with usual JavaScript (or TypeScript) related projects such as a website, or a REST API, then no, there is no need to go through all the hustle required to add WASM code to your project (if you’re having performance issues in these projects, the problems are somewhere else, not on the runtime).

Author: admin

Leave a Reply

Your email address will not be published.