There has never been a better time to write your JavaScript based application in something other than JavaScript. In this article we will take a look at some JavaScript alternatives. Although this article only focus on a few alternatives to JavaScript, there are many languages that compile to JavaScript and there is a long history of trying to replace JavaScript with something better (see CoffeeScript).
In fact Douglas Crockford was so frustrated with the implementation of JavaScript that he wrote the book JavaScript: The Good Parts to help developers stay away from the bad parts of JavaScript (there is even a chapter all about the bad parts in the book). Although JavaScript has evolved considerably over the years, Crockford’s criticisms still apply for the most part. I think this book should be required reading for any JavaScript developer, even those who are hell bent on writing JavaScript in anything but JavaScript like myself.
Like it or not, JavaScript is here to stay. JavaScript has tremendous reach because devices that have JavaScript run times (web browsers) are ubiquitous. The good news is you do not have to write JavaScript to take advantage of JavaScript’s reach. There is a galaxy of alternatives to writing vanilla JavaScript. There are so many options out there that it can be challenging to know which options you should try. I have limited the scope of this article to the JavaScript alternatives that I have experience using. If you do not like the alternatives in this article there is bound to be an alternative out there that suits your needs. I hope this article will encourage you to further explore the world of JavaScript alternatives.
TypeScript
tl;dr
C# for JavaScript. If you like C# you will feel right at home in with TypeScript.
What is it?
TypeScript is a superset of JavaScript that adds optional static typing. It is backed by Microsoft and was designed with the help of Anders Hejlsberg, creator of C#. Optional static typing means just that, it’s up to the end user to decide if they want to include static typing.
What problem does it solve?
Have you ever inherited a large JS code base and found a really hairy function with lots of arguments and no form of useful documentation about what those are supposed to be? TypeScript most obviously tries to address problems like these by adding a rich type system.
What is it like to use?
I have recently done a few projects in TypeScript in a team setting and found the type system to be very useful for communicating what various pieces are supposed to do. This made collaboration much easier because contracts between modules are clear. I found that communicating in terms of interfaces and type definitions while collaborating made it much easier to strategically divide and conquer development.
Elm
tl;dr
Elm is like Haskell for JavaScript.
What is it?
Elm is a domain specific language for creating model view update applications. Elm is opinionated. The syntax of Elm is very similar to Haskell with a limited scope.
What problem does it solve?
Elm claims to offer zero runtime exceptions. Like Haskell, if your Elm code compiles, it works. Like TypeScript, Elm is statically typed. However, the type is closer to Haskell rather than Java and C# in the case of TypeScript. Elm can also build small JavaScript assets. Smaller assets mean faster page load speeds.
What is it like to use?
Elm’s hot reloading for development provides excellent error messages seamlessly. Mistakes are immediately brought to your attention. The type system will be daunting to the uninitiated. However, it should come easily to those exposed to type systems like Haskell’s. I found Elm’s very tight feedback loop allowed me to quickly grasp the type system and by extension better understand the Haskell type system, which I had spent more time using and had read more literature about.
One thing I found particularly unergonomic about Elm is that you must manually write your own JSON decoders. So for a given piece of JSON you need to write a function that will convert the JSON data in to Elm data structures. This is opposed to something like Haskell’s Aeson library where you can just define data constructors for the JSON you expect and have generic decoder functions handle the rest. This is a controversial subject and the creator of Elm has made it clear that generic JSON decoding in Elm is not going to happen.
GDScript
tl;dr
GDScript is the python like scripting language for the Godot game engine.
What is it?
GDScript is somewhere in between python and JavaScript in terms of syntax and and architecture (there is an event loop, for example). Technically, GDScript targets web assembly when projects are exported for HTML5. By that measure, any language that can target web assembly is an alternative to JavaScript assuming you don’t need to support older browsers. If you are building a game that will target the browser, Godot is an alternative to JavaScript game engines. A major upside to choosing Godot is that you can also target Windows, Mac OSX, iOS, Android, and Linux.
What problem does it solve?
In short, making multi-platform games. However, GDScript can be used for building apps other than games and is useful for GUI oriented apps. That said, Godot is probably too heavy for web based apps where the user will expect fast initial page load times.
What is it like to use?
Working on Godot projects is heavily focused around using the Godot IDE. I find that it is more ergonomic to use the Godot IDE for running my code and use VSCode for editing my code. GDScript itself is flexible but lacks some quality of life features like lambda functions (for now). However, if building a game is your goal, the missing quality of life features are a reasonable tradeoff for the game building oriented APIs of GDScript. You can read more about my experience with GDScript here.
Parenscript
tl;dr
It’s JavaScript for Common Lisp.
What is it?
Parenscript is a subset of Common Lisp that works same way on the client and the server. Parenscript compiles to JavaScript as well as Common Lisp binaries. That opens up a world of possibilities like using the powerful Lisp macro to generate JavaScript.
What problem does it solve?
More than anything I think Parenscript solves the problem of JavaScript not being Common Lisp. By solving that problem you are now free to apply any other solution Common Lisp has to offer to your problem.
What is it like to use?
Speaking from experience, people some people seem to be highly allergic to the syntax of Lisp. If you mention Common Lisp in a room full of programmers you are almost guaranteed to hear someone say something to the effect of “but all of those parenthesis.” I wish there was help for these people because working with Lisp is a transformative experience.
Specific to Common Lisp, I have found the docs to look a little dated. Some people will take this as a sign that Common Lisp is on the decline but this could not be further from the truth. I recently went on a Common Lisp tear and was pleasantly surprised to find that many of the libraries I worked with were actively maintained.
A word of warning. Lisp will spoil all other programming languages for you. Everything else will feel inadequate. You will plod along at your day job wishing you could just write Lisp instead of whatever you are using. You will grumble about the verbosity and rigidness of other languages to anyone willing to listen. I would not wish this fate on my mortal enemy. Friends don’t let friends do Lisp. Stop reading this post and pretend you never heard of Lisp.
ClojureScript
tl;dr
So you are still interested in Lisp? Read on. ClojureScript is a Lisp for JavaScript.
What is it?
ClojureScript is part of the Clojure ecosystem. Clojure is a Lisp that focuses on functional programming paradigms. Clojure and ClojureScript are very similar but distinct languages. Clojure is compiled to JVM bytecode while ClojureScript is compiled to JavaScript.
What problem does it solve?
If Parenscript solves the problem of JavaScript not being Lisp, ClojureScript solves the problem of JavaScript not being Lisp and Lisp being too Lisp-like. Tongue and cheek comments aside, the real problem that ClojureScript solves is developer productivity. ClojureScript offers the power of Lisp macros while also interoperating with JavaScript libraries (as does Parenscript).
ClojureScript boasts an ecosystem of resume and buzzword compliant libraries that make it easy to use Lisp without taking too much heat from non-lispers. You get React via reagent, a Redux alternative via re-frame (Redux is inspired by re-frame), and you can even package your app up with electron. Your ClojureScript code can run in the browser or on the server via cljs.nodejs.
What is it like to use?
The steepest learning curve for both Clojure and ClojureScript is the tooling and error messages. There are multiple build tools like Lein and Boot. Most people seem to complain about the error messages. They can be very daunting and unclear to newcomers. Don’t let this scare you away. ClojureScript is very intuitive and with time the error messages will be easier to understand and be less frequent as your skills develop.
The syntax of ClojureScript is wonderful. If you have used JSX or TSX for React apps, you are aware of how much boilerplate this code requires. ClojureScript allows you to declare components as functions that return hiccup (a way to represent HTML as Clojure vectors). These functions are significantly more terse because nested HTML elements can be declared on a single line and there are no closing tags.
What do I recommend?
This might be a surprise, but I think you should consider using ClojureScript for your next JavaScript project. I find ClureScript to be incredibly productive. It is difficult to describe the feeling, but after using Clojure and ClojureScript my world suddenly felt much smaller and much easier to grasp. At first I could hardly get over how intuitive Clojure is. I would think of something that I wanted to do, I would do it, and it would work. Sometimes I say out loud “oh wow that totally worked!” The distance between idea and implementation was suddenly folded to the point that implementation is now just ideas. There is almost no distance between the two. A great place to start with Clojure is the book Clojure for the Brave and True.
Any Lisp is a good choice for exploring this realm of intuitiveness. However, I think that ClojureScript will come the most naturally to the uninitiated. Additionally, I think ClojureScript is an easier sell than something like Common Lisp in organizations where some team members are new to Lisp. However, that does not mean that I think ClojureScript is better. I think that teams that value fast iteration and feature velocity will greatly benefit from choosing Clojure and ClojureScript.