Mathieu Eveillard

JavaScript: When You Are the Compiler

JavaScript: When You Are the Compiler

There are still JavaScript developers who argue that a truly good developer wouldn’t need TypeScript. That’s an interesting point.

Doubt plays an important role for me; I even consider it a cardinal virtue. But in this case, allow me to say that this is simply absurd.

Let’s take a closer look 🔎

“Typing is restrictive, so I just skip it”

A classic one—it has the merit of being honest, but it makes me worry about the quality of the resulting code.

In fact, if I write (in TypeScript):

type WrappedNumber = {
  value: number;
};

const array: WrappedNumber[] = [
  { value: 0 }, //
  { value: 1 },
  { value: 3 },
];

const result = array.find(({ value }) => value === 2);

console.log(result.value);

The compiler will immediately reportts(2532): Object is possibly 'undefined'. And rightly so, since the Array.find() method returns undefined if no element in the array satisfies the predicate.

The compiler isn’t there to annoy us but rather to reveal a problem that exists, whether or not we use a type system. Saying “no” to the compiler is a bit like saying “Gravity? I don’t really like it, so I’ll do without it.”

In other words, doing without any type system doesn’t make the problem go away. It just means it will show up in production rather than in development. And that’s actually much better 👌

Someone points out that we could perform these checks at runtime and pepper our code with if. Indeed: that would amount to more or less writing a suboptimal compiler by hand. There’s a Nobel Prize in the air.

“No need for typing—I just need to look at the implementation”

In other words: “I don’t need a compiler since I know that .find() can return undefined!” This is getting better and better—so you’re suggesting we do the compilation in our heads. Don’t change a thing, guys—you’re the best 👌

Let’s examine the following code (JavaScript, this time):

const random = (min, max, generator) => min + (max - min) * generator();

random(1, 10, "generator");

At runtime, this code produces the following error: Uncaught TypeError: generator is not a function.

To avoid this error, I would have had to read the function’s implementation—the only way to know that the generator must be a function that returns a number. That’s what it means to compile from memory.

So yes, typing can be tough. But “if it hurts, it means it’s doing you good”, as Jacques Rouxel, the creator of the Shadoks, used to say. In fact, I challenge anyone to build a large-scale application in pure JavaScript. By that I mean an application with real business requirements, hundreds of thousands of lines of code, and a development team consisting of more than one developer.

“I write tests, so I don’t need a type system”

Let’s end on a more subtle note and open up our chakras. Of course, I’ve never actually heard this phrase, but it would make for an interesting argument.

Except that tests are far less effective than typing. This quote from Scott Wlaschin, a leading figure in Domain-Driven Design and functional programming, gives us a pretty good sense of this:

Unit tests have been compared to shining a flashlight into a dark room in search of a monster. Shine the light into the room and then into all the scary corners. It doesn’t mean the room is monster-free—just that the monster isn’t standing where you’ve shined your flashlight.

If you want to delve deeper into this topic, I highly recommend this excellent talk by Julien Truffaut. In any case, typing and testing are, of course, complementary.

Alright, I’ll leave you to it—I’ve got better things to do than compile code off the top of my head 😉

← All posts