This is THE TypeScript interview question. The honest answer: 90% of the time they’re interchangeable for object shapes, but the 10% matters.
In simple language — interface is built for describing the shape of an object. type is more flexible and can describe anything: objects, unions, primitives, tuples, function signatures.
What they have in common
Both describe object shapes. Both work with classes via implements. Both work with generics.
// Interface
interface User {
id: number;
name: string;
}
// Type alias — same job
type UserT = {
id: number;
name: string;
};
Where they differ
✓ extends (single + multiple)
✓ Declaration merging
✓ implements on classes
✗ Unions / intersections
✗ Primitives, tuples, mapped
✓ & (intersection)
✓ | (union)
✓ Primitives, tuples, mapped
✓ Conditional & template literals
✗ Declaration merging
Declaration merging — interface only
Declare an interface twice and TS merges them. This is powerful for extending third-party types (e.g., adding properties to Window).
interface User { id: number; }
interface User { name: string; }
const u: User = { id: 1, name: "Manish" }; // both required ✅
With type, this is an error — types can’t be redeclared.
type UserT = { id: number; };
type UserT = { name: string; }; // ❌ Duplicate identifier
Unions — type only
type can describe anything; interface can only describe an object shape.
type ID = string | number; // ✅ type can
type Result = { ok: true } | { ok: false; error: string };
// interface ID = string | number; // ❌ syntax error
Extending
Both can extend, just with different syntax.
// Interface extends interface
interface Animal { name: string; }
interface Dog extends Animal { breed: string; }
// Type uses intersection
type AnimalT = { name: string; };
type DogT = AnimalT & { breed: string; };
Implements (with classes)
Both work, no real difference here.
interface Logger { log(msg: string): void; }
class ConsoleLogger implements Logger {
log(msg: string) { console.log(msg); }
}
The practical rule
- Use
interfacefor object shapes that are part of a public API. Declaration merging is a nice escape hatch. - Use
typewhen you need unions, intersections, tuples, mapped types, or conditional types. - Be consistent within a codebase. Pick a default and stick with it.
A common convention: interface for object shapes, type for everything else.
Performance note
For very large unions, interface (with extends) is slightly faster for the compiler than type with intersection. Mostly irrelevant unless you’re typing thousands of objects.
Interview soundbite
“For plain object shapes they’re nearly identical. The differences: interface supports declaration merging and only describes objects; type is a general alias that can describe unions, primitives, tuples, and mapped types. Use interface for public object APIs, type for everything else.”