When do you choose interface vs type alias?
Take a moment.
Say your answer out loud or write it down first — retrieval is what makes it stick. Reveal when you're ready.
Short answer
Both describe object shapes and are mostly interchangeable. Interfaces support declaration merging and are ideal for public object contracts/classes; types are required for unions, intersections, mapped/conditional types and primitives.
Detailed explanation
interface defines object contracts: implementable by classes, extendable via extends, and open to declaration merging — two interfaces with the same name merge their members, which is how libraries augment globals like Window. type creates an alias for any type expression: unions ('a' | 'b'), tuples, function signatures, conditional and mapped types, primitives — things interfaces simply can't express. Intersections (&) work with both but behave subtly differently from extends during conflict resolution: intersection members conflicting become never rather than raising an error. Performance-wise differences are negligible today. Team consistency matters more than dogma: many style guides say 'use interface for objects others may extend or merge, type for everything else' — being able to articulate both sides beats picking one blindly.
Example
// Declaration merging — interfaces only:
interface Window { analytics?: Tracker }
declare global { interface Window { __DEV__?: boolean } }
// Unions & mapped types — types only:
type Status = 'idle' | 'loading' | 'error';
type Nullable<T> = T | null;
type Handlers = { [K in `on${Capitalize<Status>}`]?: () => void };Interview tip
Lead with 'mostly interchangeable', then name the two hard differentiators: merging (interfaces) and unions/mapped types (types). That structure reads as considered judgment.
Common mistakes
- Claiming one performs better than the other.
- Not knowing declaration merging exists.