... And maybe we want set-operations in the future...
We spend most of our time reading code. If the Casey's code snippets are easier to reason about (which they are, especially as the codebase get larger), that's a big win. I'd imagine you want to optimize for code that is easy to (re)write, rather than minimize the number of key strokes while increasing the time spent understanding the code.
What is adding a polygon going to do? Either back to the 'bad' interface to hide variable object size, extend to a tagged union with a size of the biggest datastructure - hurting cache performance each time it grows -, or an involved Object of Arrays structure - not good for clarity but great for performance.
All while having to remember which field, width or height, to use for the circles radius.
As demonstrated in the example, extensibility costs in performance, and also sometimes in comprehension. If we apply the “clean code” rules as a matter of course, we pay this price always.
In my opinion, we should use interfaces etc at module boundaries only.
if he simply kept the original "unoptimized" switch case method, what you say wouldn't apply. it couldn't. from a pure feature standpoint, a switch case is functionally identical to polymorphism except that you can't add types that are unknown at compile time (like loaded at runtime as an extension from a library or something). and that version is already faster.
what the blog post does after that point is merely point out that by having everything in one place, you see opportunities to optimize. this is a separate thing where you still have to consider whether that actually makes sense.
like, if you can guesstimate that an entirely different type is likely to enter the picture at some point, you may skip this optimization. if production realities mean that code needs to be faster, you can still apply it and add some comments about how to change it back, or just keep the original version commented out with a reference for why its there. and so on.
In non-performance-critical areas, it's pretty important that when the original dev team leaves, new hires can still fix bugs and add features without breaking things.