Programming Fundamentals › Type Systems
Type System
The rules a language uses to assign and check types.
Also known as: type checking, types in programming languages
A type system is the set of rules a language uses to assign types to values and expressions, and to decide what operations are allowed on them. Its job is to catch nonsense (like multiplying a string by a date) and to describe what code expects.
Several choices shape how a type system feels:
| Question | Options |
|---|---|
| When are types checked? | before running, or at runtime (static vs dynamic) |
| How strict are conversions? | strict or lenient (strong vs weak) |
| Must you write the types? | explicitly, or inferred (type inference) |
| Is compatibility by name or shape? | by declared name, or by structure (structural vs nominal) |
| Can types be parameterized? | yes, with generics |
| Can a value be one of several types? | with unions and discriminated unions |
Is null a normal value? | or tracked in the type (nullable types) |
function area(r: number): number { return Math.PI * r * r; }
area("big"); // compile error: string isn't number
What a type system gives you
- Early error detection, and fewer runtime surprises.
- Documentation in signatures.
- Tooling: autocomplete, refactoring.
- Design pressure: modeling the domain with types (an
OrderIdisn’t aUserId) makes wrong states hard to write.
Its limits
A type system proves only what it’s designed to. It can’t know that a string is a valid email, or that an API returned the right shape, so you still need validation and tests (runtime validation). Stronger systems can express more but are harder to learn.
When choosing a language or tool, ask what mistakes its type system can and can’t catch.