How to write a great switch statement in JavaScript
Tags: javascript, codequality, fundamentals
Published: 2020-06-25 19:32:31

Leaving all former and historical discussion on *"why not using `switch` statements"* behind, I'd like to show my approach on how to get the most out of it:

```javascript
function processByType ({ type, ...args }) {
  switch (type) {
    case CONST_VALUE_A:
      return processArgsA(args)
    case CONST_VALUE_B:
      return processArgsB(args)
    case CONST_VALUE_C:
      return processArgsC(args)
    default:
      throw new Error(`unknown type ${type}`)
  }
}
```

Let me explain a bit, why I think this is a great `switch` concept:

## Single responsibility

I think we should approach the `switch`with something similar to the single responsibility principle. 
Basically, it's purpose is to decide which case branch to execute by a given value. The only reason to change the switch code is an updated logic on the value mapping (which case branch to execute, based on which value of `type`).

Derived from this assumption, we may conclude the following:

## It has no operational code in branches

Let the `switch` defer processing to external functions, because it is not the responsibility of the `switch` to implement the concrete processing.

It should also contain no pre- or post-processing code but just pass through arguments from input to the defined functions.

## It is wrapped in a function

The `switch` can only be isolated when wrapped in a function. Also increased the reuse and testability.

## It uses constants as `case` match conditions

This is a tricky one and I am 50/50 on it. On the one hand using constants reduces the error rate of typos. On the other hand it makes the function dependent on some external definitions.

I think this depends on the case and the overall need for scalability. Anyway, I tend to favour constants from an aesthetic point of view. 


## It does not use `break` statements

The `break` is something like the spaghetti-code's topping to me. It "breaks" control flow in an unnatural way, where it jumps like a `goto` to an invisibly tagged point after the `switch` block.

However, since there is no need to execute code after the `switch` block we can safely return the result of the function called in the `case` branch.

## It throws and error as default

Defining a `default` and not throwing an error is like writing an `if-else` logic with multiple if-conditions - you can't control the reason why it branched into the `else`.

The same thing applies for `default`. The `type` value could by anything, ranging from `undefined`, `null` or a totally different type.

To indicate such an undefined state it is therefore conclusive to throw an error here and examine the source of this uncovered `type` value.

## What do you think?

Note, that this has derived from my personal experience, mixed with what I picked up from readings or observed from other projects (for example the usage of constants in branching logic is something I have learned when working with Java). 

If you still think there is something flawed in this concept and `switch` should just be banned from the language set, please let me know.