Back to all articles
Technology

Type Systems as Communication

Types are not just a tool for catching bugs. They are a language for expressing intent — and the most important audience is future collaborators.

T

Theo Nakamura

Software Engineer

May 28, 20265 min read

A type annotation is a note to the future. When you write that a function accepts a UserId rather than a string, you are telling every developer who reads that code something important about what this value means.

This is the part of type systems that gets undersold. The pitch is usually about catching errors at compile time, and that is real and valuable. But the deeper value is communication.

The Difference Between Types and Validation

Types and validation are treated as alternatives in many codebases. They answer different questions. Validation answers: is this data what I expect right now, at runtime? Types answer: what does this data mean, and what can I do with it?

The value of a type like UserId over string is not that it prevents you from receiving an invalid user ID at runtime. It is that it prevents you from accidentally passing a PostId where a UserId is expected.

Making Illegal States Unrepresentable

The most powerful use of a type system is making certain states impossible to represent. A discriminated union eliminates invalid states at the type level. The bugs in your authentication logic simply cannot exist.

The Cost of Expressiveness

More expressive types require more thought upfront. The trade-off is real, and the right balance depends on the codebase, the team, and the rate of change.

What I am arguing against is treating types as purely defensive. At their best, types are a design tool. They force you to articulate what things are before you write the code that handles them.

A Practice

When I write a new module, I often write the types first and leave the implementations empty. The types become a sketch. They tell me whether the design makes sense before I have invested hours in the implementation.