A New Coding Style for Switch Statements in JavaScript/TypeScript

nebrius

Bryan Hughes

Posted on May 16, 2019

A New Coding Style for Switch Statements in JavaScript/TypeScript

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).

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);
}
Enter fullscreen mode Exit fullscreen mode

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

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}`);
}
Enter fullscreen mode Exit fullscreen mode

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:

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}`);
  }
}
Enter fullscreen mode Exit fullscreen mode

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 that automates another approach I hadn't thought of before:

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
Enter fullscreen mode Exit fullscreen mode
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
Enter fullscreen mode Exit fullscreen mode

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

💖 💪 🙅 🚩
nebrius
Bryan Hughes

Posted on May 16, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related