How to use pattern matching in JavaScript - an alternative?
Tags: javascript, functional, programming, softwaredevelopment
Published: 2020-07-19 09:53:48


We are going to quickly see what is pattern matching, see basic examples of it in [Scala](https://www.scala-lang.org/) and make an analogy with one less known usage of JavaScript switch statement.

There is no native support for pattern matching in JavaScript. However, there is an open [proposal](https://github.com/tc39/proposal-pattern-matching) which is great and it would be nice to have support and use it in the future if it gets approved and goes through all of the stages.

_Note: this isn't a tutorial about Scala pattern matching and the given examples will be simple ones without going into details._

Let's get started!

---

### What is pattern matching?

It is a mechanism for checking/testing a value against a given pattern. The match should be exact. The logic for the first pattern that matches the value is executed. The patterns can vary and the functional programming languages support a variety of different usages.

Based on the [Scala docs](https://docs.scala-lang.org/tour/pattern-matching.html):

> It is a more powerful version of the switch statement in Java and it can likewise be used in place of a series of if/else statements.

They are far more powerful than the usual `switch` statement. We will see how we can make an analogy with JavaScript `switch` statement though and use it in a way that gives us more control to write complicated expressions.

### Scala pattern matching examples

One of the simplest cases is match by value:

```
def getMonthName(month: Int): String = month match {
  case 1 => "January"
  case 2 => "February"
  // .etc
  case _ => "Unknown"
}
getMonthName(13)  // Unknown
getMonthName(1)  // January
```

JavaScript version:

```javascript
const getMonthName = (month) => {
  switch (month) {
    case 1:
      return 'January';
    case 2:
      return 'February';
    // .etc
    default:
      return 'Unknown';
  }
};

getMonthName(13); // Unknown
getMonthName(1); // January
```

We can have matching on type:

```
abstract class Device
case class Phone(model: String) extends Device {
  def screenOff = "Turning screen off"
}
case class Computer(model: String) extends Device {
  def screenSaverOn = "Turning screen saver on..."
}

def goIdle(device: Device) = device match {
  case p: Phone => p.screenOff
  case c: Computer => c.screenSaverOn
}
```

There are a lot of other different usages of pattern matching that Scala supports but this is not the focus of this blog post. If you are interested in seeing them you can check out [pattern matching](https://docs.scala-lang.org/tour/pattern-matching.html) and [match expressions](https://docs.scala-lang.org/overviews/scala-book/match-expressions.html).

### JavaScript switch statement quick overview

From my experience in almost all of the places I have worked, `switch` is used in its traditional form as `switch (someValue)` and then `case` statements with simple numbers or strings.

Let's see an example from [MDN docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch):

```javascript
const value = 'Papayas';
switch (value) {
  case 'Oranges':
    console.log('Oranges are $0.59 a pound.');
    break;
  case 'Mangoes':
  case 'Papayas':
    console.log('Mangoes and papayas are $2.79 a pound.');
    // expected output: "Mangoes and papayas are $2.79 a pound."
    break;
  default:
    console.log(`Sorry, we are out of ${value}.`);
}
```

This is great but it feels like we are limited to simple values only. What if we want to add additional conditions or we want to use more complex data structures like lists, dictionaries, .etc?

### One less known usage of switch statement in JavaScript

If we try to formulate a question of what we want to do, it would be - what should we do if we want to write whatever expressions we want in the `case` statements and if one is true execute some logic?

By asking the question we have already answered it by **_if some of them is true_**. We can pass `true` as value for our `switch` statement and then the logic for the first case expression that evaluates to true will be executed.

Let's take a look at an example:

```javascript
const getCompactAmount = (amount) => {
  switch (true) {
    case amount / 1000000 >= 1:
      return `${amount / 1000000}M`;
    case amount / 1000 >= 1:
      return `${amount / 1000}K`;
    default:
      return amount;
  }
};

getCompactAmount(2000000); // 2M
getCompactAmount(5000); // 5K
getCompactAmount(123); // 123
```

We want to match our expressions to `true` which gives us the power to write whatever expressions we would like with whatever complicated conditions we need.

### Conclusion

This, of course, can be achieved by using `if/else if/else` statements and I guess it is a matter of preference what to use. I am not saying that this should be always used but it gives some nice opportunities and I think is a less known usage which I haven't seen much. As someone who isn't a big fan of `switch` statements and tried to avoid using them, I would say that after I have used `switch (true)` for a while I am more than happy with it. I find it much easier to read than multiple `if/else if` statements and less error-prone.

Thank you for reading this to the end. I hope you enjoyed it and learned something new. If so, please follow me on [Twitter](https://twitter.com/BelevMartin) where I will share other tips, new articles, and things I learn. If you would like to learn more, have a chat about software development, or give me some feedback, don't be shy and drop me a DM.