Type systems are leaky abstractions: the case of Map.take!/2

Elixir’s new 'take!' plan sparks a type war: 'Just code it' vs 'Prove it'

TLDR: Elixir devs toyed with a Map.take! function that fails if keys are missing, but typing it precisely sparked a split: optional, flexible types vs strict, provable guarantees. Commenters debated “Any” type leaks, suggested optional returns instead of errors, and turned the ‘keys’ question into a bigger fight about adding static types to a dynamic language

Elixir folks floated a spicy idea: Map.take!/2, a “grab these keys or blow up” function. Sounds simple… until the new type system enters the chat. The blog asks how to type this cleanly so the result says exactly which keys you got. Cue community fireworks. One side wants confidence, the other screams “you can’t promise that!” and the comments go full courtroom drama.

User mcphage argues the feature defeats its own purpose if you can’t be certain the keys exist in all cases—hello, Schrödinger’s keys. Meanwhile, travisgriggs drops a mic with the 90/10 rule: types give big wins early, then turn into a grind, praising Python’s chill “opt-in” vibe. Over in the corner, codebje calls the title clickbait and says the real issue is trying to strap a fancy type system onto a language where “anything goes” maps rule—aka the dreaded Any “leaks everywhere” problem.

logicprog proposes a clean fix: don’t blow up, just return an optional result (Some/None). foxes gets philosophical about lists vs maps, teasing that Map.take! is pretending to be total when it’s not. TypeScript fans flash their badges with keyof receipts, while Elixir traditionalists mutter “just write two tiny functions.” The mood: half memes about “lost keys,” half existential sighs about static types in dynamic lands. Everyone agrees on one thing: the keys discourse unlocked a lot of feelings

Key Points

  • Elixir’s Map.take/2 returns a subset of a map and ignores missing keys.
  • A proposed Map.take!/2 would raise an error if any requested key is absent.
  • Dynamic Elixir allows a simple Map.take!/2 implementation using Map.fetch!/2.
  • The current best type signature for Map.take!/2 (map(), [term()] -> map()) is too broad and does not describe the output’s key shape.
  • TypeScript’s keyof (v5.9) is highlighted as a way to encode key constraints and return types that reflect selected keys.

Hottest takes

"the goal of the function is to return a map where we are certain the given keys exist!" — mcphage
"You get 90% of the gains for 10% of the effort." — travisgriggs
"shoehorning a richer type system atop an Any-typed language is leaky." — codebje
Made with <3 by @siedrix and @shesho from CDMX. Powered by Forge&Hive.