The Default-Case Pattern
A cleaner way to write switch statements.
Switch statements can be frustrating. With so many unique keywords (switch
, case
, break
, default
) to remember, and the obscure behavior of it’s control flow, it’s one of the most complex primitive constructs you’ll ever learn in programming.
A common use for switch statements in JavaScript (and many other languages) is resolving something based on an enumerable value. An enumerable is a finite set of unique values a variable can be. A simple example would be CSS positions:
enum CSS_POSITIONS {
static
relative
fixed
absolute
sticky
}
You can imagine there would be a switch statement somewhere in your browser that executes different code paths to modify an element’s position based on this property, and if position
is undefined, the code path for static
is executed as the default case. That function might look something like this:
This is fine. However, we’re calling this.positionStatic()
twice (in the case ‘static'
and default
). There are several ways we can clean up this code and make it DRY. The common thing to do would be to simply remove the case for static
and let default
catch it.
I’ve never liked this solution. It makes the code DRY, but it decreases the explicitness of the code and makes it less readable. So I started thinking of ways to make this code DRY while retaining the readability of explicitly defining what the default case is.
To walk though this solution, we’re going to switch (see what I did there??) to an example with emojis because they’re more fun. 😃
Here’s a simple function that maps keys to emojis. However, we don’t have a default case that makes sense. We could just remove the default and set a default value for value
as it comes into the function since there’s only a finite set of possible values and you handle all of those cases. That is completely valid syntax-wise, but that doesn’t handle misspellings or type mismatches (What if someone tries to pass an array?). And if you’re using a linter rule that enforces defining a default for switch statements, then this won’t work either.
Let’s instead opt to return a smile emoji as the default:
Good, now that we have it working correctly, let’s make it DRY by leveraging the execution behavior of switch statements and combine default
and case 'smile'
:
By combining these two cases into one, the switch statement will match on either “smile” or any unhandled case. Although case ‘smile'
isn’t required for this to work, I think it makes the code a lot more readable because it’s clear what all the possible values are and which one is the default value. Plus it is almost English-readable in this format.
We can go one step further and move the default case to the top of the switch statement so that it’s immediately obvious for someone new reading this code:
I’ve never seen anyone else use this pattern before, but I’m probably not the first to propose this pattern. I call it the default-case pattern, but maybe there’s a different name for it.
I welcome any feedback and criticisms of this pattern, please leave a comment with your thoughts.