A New Coding Style for Switch Statements in JavaScript/TypeScript
Tags: javascript, typescript, discuss, coding
Published: 2019-05-16 16:08:42

---
title: A New Coding Style for Switch Statements in JavaScript/TypeScript
published: true
description: I created a new coding style for switch statements to get around scoping issues
tags: javascript, typescript, discuss, coding,
---

I've recently adopted a new coding style for `switch` statements in JavaScript (well, technically TypeScript), and I'm really curious to hear what you all think about it!

Before I discuss the style, let me explain the problem I'm trying to solve. It's not uncommon for switch statements to have somewhat-repeated code between cases, but with variations in each case such that you can't easily abstract it. Let's take this example, written in ES5 (I promise there's a reason why).

```javascript
switch (body.type) {
  case 'isBasic':
    var entry = getBasicEntry(body.id);
    console.log('Processing basic entry "' + entry.name + '"');
    doBasicProcessing(entry);
    break;

  case 'isCustom':
    var entry = getCustomEntry(body.id);
    console.log('Processing custom entry "' + entry.name + '"');
    doCustomprocessing(entry);
    break;

  default:
    throw new Error('Unknown flag ' + myFlag);
}
```

Cool, it's a basic switch statement and it works fine. Now, let's convert this to ES2015+.

```javascript
switch (body.type) {
  case 'isBasic':
    const entry = getBasicEntry(body.id);
    console.log(`Processing basic entry "${entry.name}"`);
    doBasicProcessing(entry);
    break;

  case 'isCustom':
    const entry = getCustomEntry(body.id);
    console.log(`Processing custom entry "${entry.name}"`);
    doCustomprocessing(entry);
    break;

  default:
    throw new Error(`Unknown flag ${myFlag}`);
}
```

Uh-oh, we now get a `SyntaxError` exception when we run this code! The problem here is that `const` variable name `entry` cannot be declared twice in the same scope. Because of how scoping rules work, the entire `switch` statement is one single scope.

We could solve this by naming each `entry` with a different variable name, but honestly I find that kind of annoying. We could also create a helper function for each case, but that feels excessive to me for such short case statements.

So here's what I figured out, and I've started using it in all my code:

```javascript
switch (body.type) {
  case 'isBasic': {
    const entry = getBasicEntry(body.id);
    console.log(`Processing basic entry "${entry.name}"`);
    doBasicProcessing(entry);
    break;
  }

  case 'isCustom': {
    const entry = getCustomEntry(body.id);
    console.log(`Processing custom entry "${entry.name}"`);
    doCustomprocessing(entry);
    break;
  }

  default: {
    throw new Error(`Unknown flag ${myFlag}`);
  }
}
```

I wrap each case statement in `{}`, which creates a new scope on a per-case basis. This solves the problem, and I think is kind of elegant myself. It's not very common though.

What do you all think? Does this seem like a good approach? Do you have a different approach that you use? I'd love to hear it in the comments!

## Update:

Thank you all for the discussion so far, it's been great! I ended up creating a new module called [conditional-reduce](https://www.npmjs.com/package/conditional-reduce) that automates another approach I hadn't thought of before:

```javascript
const { reduce } = require('conditional-reduce');
 
console.log(reduce('dog', {
  dog: () => 'Dogs are great pets',
  cat: () => 'Cat\'s are also great'
})); // Prints "Dogs are great pets"
 
console.log(reduce('bird', {
  dog: () => 'Dogs are great pets',
  cat: () => 'Cat\'s are also great'
})); // Throws 'Invalid conditional value "bird"' exception
```

```javascript
const { curry } = require('conditional-reduce');
 
const dogReducer = curry({
  dog: () => 'Dogs are great pets',
  cat: () => 'Cat\'s are also great'
});
 
console.log(dogReducer('dog')); // Prints "Dogs are great pets"
console.log(dogReducer('bird')); // Throws 'Invalid conditional value "bird"' exception
```

Thank you @avalander and @john_papa for the discussion that prompted this!