How to use the
switch statement when checking whether some object is an instance of some class.
If you don’t like long reading, skip to solutions: constructor based and DSL based.
Imagine code like this:
This code works just fine and as expected (try it). But isn’t there a better way? Without multiple
if statements? This is where the
switch statement comes to play. We usually use the
switch statement when we have a few fixed amounts of values and we want to do different things for different values. For example:
The problem with the
shape instanceof Point is that it cannot be simply transformed into the
switch statement. This does not work:
Why? The interpreter would simply check whether the
shape variable equals the
Point variable and that is not the case. It does not check if
shape is an instance of
Point. It checks if
There is a hack. You can check whether the
constructor property equals the class. The
constructor property returns a reference to the Object constructor function that created the instance object. Roughly speaking, it contains a reference to the Class.
It works! (try it) But there is a significant drawback:
It checks if
constructor equals the given class. It does not check if it is an instance of this class – it does not work well with “inheritance”. If we add another shape called
RedCircle that extends
switch statement fails to recognize it as a
It prints “Unknown object…”. (try it)
Not that TypeScript does infer the type. Let’s add property
radius to the
Circle class. We should be able to read the property is we check the
shape is actually a
And it works (try it).
Write Your Own Mini-DSL
switch syntax is not the answer. Maybe no syntax is the answer. Maybe mini-DSL is the answer. DSL stands for domain-specific language. We can simply ignore the
switch statement and we can even ignore the
if statement. We can write our own function with some nice API to check whether the
shape variable is
Circle or not. What would you say to this syntax:
Is it readable? I’d say yes. Don’t like the method names? Use any better naming you like! That is the magic. And how to implement it? I usually write it using a few nested functions:
If it gets too big, I refactor it (try it). Why do I like it?
- It reads nicely!
- I can implement any logic I want. With the
switchstatement I cannot implement the proper
instanceoflogic. This way? No problem.
- I can use domain-specific names of the methods. The method
dois not exactly domain-specific, but we could use something like
drawOnCanvasto be more specific.
- We can implement additional logic there.
What are the drawbacks? As far as I know, it’s not possible to implement lazy evaluation: all of the conditions are always evaluated. That should not be an issue in most cases.
Do you have any better ideas?