You’ve seen the code:
type MaybeThing = ExactThing | NeverUsed | PossiblyThing | undefined | null;
function doStuff(input: NarrowedButPossiblyNull<Validated<MaybeThing>>) { ... }
This isn’t clarity. This is defensive architecture — designed to impress other engineers, not serve users. And while it may compile without errors, it screams of insecurity. These aren’t safety nets. They’re safety theater.
Because you can wrap User
in 14 layers of branded types, discriminated unions, and schema validators… and still fail to handle an empty object from your API.
TypeScript Should Be a Lever, Not a Lifestyle
When you start optimizing for what the compiler understands rather than what your teammates understand, you’re off the rails.
Clear:
type PostStatus = 'draft' | 'published' | 'archived';
Compulsive:
type PostStatus = keyof typeof PostStatusMap as const
At some point, the code stops being about outcomes and starts being about expressiveness. It becomes art for the compiler, not a tool for the job. That’s how you get frozen codebases: nothing can change without triggering a cascade of type errors. Refactoring becomes radioactive. Simplicity dies a slow death by a thousand generic constraints.
Ship Builders, Not Type Priests
The best TypeScript codebases are boring. Boring is good. It means things work. It means types help without hurting.
The worst? They’re baroque fortresses — obsessed with edge cases and hypotheticals. Shipping becomes a bureaucratic nightmare. In these codebases, correctness is defined not by what the app does, but by what the type checker permits you to do.
That’s not engineering. That’s orthodoxy.
Don’t Mistake Safety for Sanity
The runtime is the final judge — not the compiler, not your linter, and definitely not the smug Medium post that convinced you to build a recursive JSON inferencer just to parse a string. Users don’t care how clever your types are. They care if your app crashes.
In Summary
- Use TypeScript. It’s great.
- Avoid type maximalism. It’s not.
- Prioritize clarity and confidence over cleverness and complexity.
Remember: you’re building software — not writing academic papers for a TypeScript conference.
You are not your types.