As developers, we spend every day writing control flow. Sometimes, we end up with long, nasty conditions that we wish we could’ve expressed in a cleaner way. The pattern matching proposal may help us do so, by giving us the option to use the JS destructuring syntax to specify the precise shape of the data we wish to use for our condition.

Limitations of existing control flow

Before we get into the proposal, let’s analyze the status quo. There are 2 common control-flow options you are probably familiar with in JavaScript

If statement

Switch statement

If Statement

If you’ve written code, then you’ve probably written an if statement. They’re simple, powerful and fundamental to programming. In JS, you can insert any value or expression as the condition, and it will be evaluated as truthy or falsey.

Here’s an example of a naive http response handler, where I’m only expecting 1 of 3 status codes, and otherwise falling back to a catch all.

function handleHttpResponse(res) { if (res.status === 200) { handleSuccess(res); } else if (res.status === 400) { handleBadRequest(res); } else if (res.status === 500) { handleServerError(res); } else { handleUnexpectedResponse(res); } }

Ok, that works. There’s a clear weakness to this approach though -> It’s not DRY (Don’t Repeat Yourself). I’m repeating the equality check on each line. This is because each condition has no prior context that I’m matching against a variable ‘res’, so I have to specify it each time.

Can I update this to indicate I’m going to be matching the same value each time? Yes, I can, using a switch.

Switch Statement

Many programming languages also include the concept of a switch statement. The form is generally similar – specify the variable you are switching on up front, then designate the action to take when it matches certain values.

Let’s return to my http handler to demonstrate this in JS.

function handleHttpResponse(res) { switch (res.status) { case 200: handleSuccess(res); break; case 400: handleBadRequest(res); break; case 500: handleServerError(res); break; default: handleUnexpectedResponse(res); } }

Now I’ve avoided repeating the equality check. This removes some noise, making the flow easier to read.

Unfortunately, this approach still has a weakness[1] – I can only match against a single primitive value. What if I wanted to designate a case where res.status is 200 and res.body is truthy? At that point I’d need to go back to if statements and do something like:

if (res.status === 200 && res.body) { handleSuccess(res); }

However, now I’m back to the problem from earlier where I’ll be repeating myself.

I think it’d be nice if I could be DRY and match more than one value per condition. Turns out, I’m not the only one thinking that.

Pattern Matching

The TC39 is considering a proposal to add a ‘Pattern Matching’ expression to JavaScript. It’s currently at Stage 1 of their process, as of June 2019. It has been described as a ‘Super switch’[2]. With the current form of the proposal, our above example would look like this:

function handleHttpResponse(res) { case (res) { when { status: 200, body } -> handleSuccess(res); when { status: 400 } -> handleBadRequest(res); when { status: 500 } -> handleServerError(res); when _ -> handleUnexpectedResponse(res); } }

Let’s break down what’s happening here:

We’re specifying the res object as the value we’re going to switch on.

Using the destructuring[3] syntax, we’re specifying the pattern of values from the res object we’d like to match.

The end result is that we can be very specific about the shape we want our data to match, in a terse form.

So is this just for matching object patterns? Nope. The proposal covers matching against all standard data types in JS, including arrays.

You can dig into the proposal and see some more exotic examples here.

One important note – as this is “Stage 1” of the TC39 Process[4], the syntax may change significantly, or the proposal could be scrapped altogether. In fact, the current ‘case’ syntax is controversial as it’s seen to possibly cause confusion with the existing switch statement syntax, that also uses the case keyword. Don’t get ahead of yourself and plan to use this just yet.

Thoughts

There is a term in programming called “footgun”. It describes a feature that enables the user to shoot themselves in the foot. It could be argued that this pattern matching expression is an example of a footgun. Code that depends on checking many values for control flow, within the body of a single function, can be brittle. You can make a case that rather than encouraging this style of programming, the language should introduce features that push away from it.

That being said, other languages that are generally well-regarded by software engineers have adopted very similar features. These include Rust and C#. In that sense, we could see JS is in “good company” of other languages that have decided this is a valuable asset to the developer toolset. It should be noted though that those languages are statically typed, which means they can take this concept further and do matching against types.

I am of the opinion that programming languages should give developers power and flexibility. Rather than being paternalistic and cynical of developer intent, we should respond to what developers say they need and give them helpful tools to overcome them. I know there are times in my own code where I would have used this feature to improve the code readability. Could I have written the overall solution another way? Perhaps, but that doesn’t change the fact that this feature would improve its current state.

I welcome the continuing development of the JS language and the role the TC39 plays in it. This proposal is just one of many interesting ideas being considered. I hope it’s got you thinking about what features you’d like to have added to the language to help solve problems you or your team encounter regularly.

If you’d like to know more about the work the TC39 does in developing the JS spec, check out their new information site here. Keep an eye on our blog going forward if you’d like to see more discussions about the future of both JavaScript and the web as a whole.

[1] More than one if you know that excluding the break statement will cause you to fall through to default, but we’re focused on condition matching power here.

[2] https://docs.google.com/presentation/d/1WPyAO4pHRsfwGoiIZupz_-tzAdv8mirw-aZfbxbAVcQ/edit?usp=sharing

[3] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

[4] https://tc39.es/process-document/