TypeScript Interfaces vs Types: When to Use Each
Interfaces and type aliases overlap heavily in TypeScript, so the real decision is about extension patterns, readability, and team conventions.
Most teams overstate the difference
Interfaces and type aliases can both describe object shapes, which is why this debate often gets framed as more dramatic than it is. In everyday application code, either one can work. The more useful distinction is what kinds of composition you expect.
Interfaces are strong when you want something object-shaped that can be extended or merged cleanly. Type aliases are more flexible because they can represent unions, intersections, tuples, primitives, mapped types, and other patterns that go beyond plain objects.
Use interfaces when
- You are describing the public shape of objects, props, request payloads, or class contracts.
- You want clear extension through
extends. - Your codebase benefits from declaration merging or library-style augmentation.
Use type aliases when
- You need unions or computed composition.
- You are modeling state variants or discriminated unions.
- You want one tool that also covers primitives, tuples, and helper compositions.
The trap to avoid
The problem is not picking the “wrong” keyword once. The problem is mixing conventions so randomly that the codebase becomes harder to scan. If every object shape is a type alias in one folder and an interface in the next, the team spends energy decoding style instead of reading intent.
A pragmatic convention
A lot of teams do well with a simple rule: use interface for stable object contracts and component props, use type for unions and more expressive compositions. The exact rule matters less than consistency. TypeScript already has enough complexity. Your naming conventions should be reducing that burden, not adding to it.