2023-07-27
Unsoundness with TypeScript Getters
While reading The Seven Sources of Unsoundness in TypeScript I was thinking other methods to trick TypeScript in inferring the incorrect type. Turns out you can use getters to trick typeguards into thinking a variable has a certain type at compile time, while at runtime it has another.
We can exploit the TypeScript behavior that expects a getter to return the last value that was set on an object in the same synchronous scope and the fact that a getter is a function that can return anything it wants at runtime.
The following code will compile without problems, but at runtime it will call callAliveCat() with a DeadCat half of the times.
For the entire if block the compiler thinks box.observe is AliveCat, just because it was when isAlive() was invoked.
If we make observe() a function instead everything works correctly.
In my opinion TypeScript should be fixed to keep into account this edge case rather than assuming the developer never implements dynamic getters.