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);
}
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}`);
}
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}`);
}
}
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.
#javascript