3/16/2026 at 1:35:03 AM
The article's summary is fair, but the title is IMO a bit of a click bait, because the problem as described really is that "shoehorning a richer type system atop an Any-typed language is leaky." The Any type leaks through. The principle that a Map from Any to Any is the only data structure of note leaks through.Trying to make that work for static validation requires dependent typing: the type of the result depends on the term passed in. Or, you could use row types, record types, or any of the other data structures richly typed languages use at their core to be more expressive of intent than just a Map from Any to Any.
by codebje
3/16/2026 at 2:33:42 AM
The title is really quite an annoying abuse of the term "leaky abstraction".by andrewflnr
3/16/2026 at 11:59:07 AM
The author doesn't understand what a leaky abstraction is:He writes:
"And in order to understand why that’s the case, you need to start digging into the workings of the type system (hence a leaky abstraction)."
Then he proceeds to just write more Typescript without dropping down to reading the Typescript compiler source code, which is what generally happens when you have to deal with a leaky abstraction.
When you have an ORM that generates SQL, but you have to read the generated SQL for performance reasons (N+1, etc), that's a leaky abstraction. The details end up leaking through.
This doesn't work with Typescript, since Typescript types don't appear in the generated Javascript code. The type system doesn't try to hide an underlying system that could possibly leak through. The type system is a new thing that wasn't there before.
What's particularly annoying about the blog post is that the topic at hand actually has very little to do with type systems. It's primarily about compile time evaluation of code. The keys needed for map access need to be known at compile time and by threading them through an if(Math.random() < 0.5), or a keys = keys.map(x => x); the compiler would have to evaluate every possible code path symbolically to generate a type signature. After all, the code could have been keys.map(x => x + "abc") or any other arbitrary expression that can be evaluated at compile time.
The compiler doesn't really give a damn about the types here, because they are kind of irrelevant and crystalize out of the results of compile time evaluation. keys.map(x => x) and keys.map(x => x + "abc") both take a list of strings and output a list of strings. The types are exactly as you expect, but the concrete values are different.
The only way out of this with a type system would be to encode values into the type system itself, which is kind of antithetical to the idea of typing.
by imtringued
3/16/2026 at 2:39:51 AM
Honestly I got hung up on understanding why for Typescript the declaration of `keys` shouldn't be:let keys = (keyof typeof users)[]
Like I get it's a contrived example and maybe I'm missing some nuance to it, but if we're obsessed with type-safety why are we treating a array of strings as an array of keys (which are more like atoms)?
I thought the answer might be we're looking for duck typing-ish behavior, but then the proposed take signature doesn't work either?
by BoorishBears