Master the differences between interfaces and type aliases, including declaration merging, object extension, and architectural best practices.
Discover how TypeScript infers types automatically and how let versus const declarations shape wide types versus narrow literal types.
TypeScript provides two primary keywords for defining object shapes: interface and type. While they overlap significantly, they possess distinct capabilities.
extends)An interface defines an object contract that can be extended using the extends keyword:
interface User {
id: number;
name: string;
}
// Extending an interface
interface AdminUser extends User {
permissions: string[];
}
const admin: AdminUser = {
id: 1,
name: "Sarah",
permissions: ["read", "write", "delete"],
};
Multiple interface declarations with the same name in the same scope automatically merge their property definitions:
interface Window {
customTitle: string;
}
interface Window {
customVersion: number;
}
// Window interface now contains BOTH properties!
&)Type aliases use Intersection Types (&) to combine object shapes:
type AuditLog = { timestamp: Date };
type UserLog = User & AuditLog; // Intersection combining shapes
| Feature | Interface | Type Alias |
|---|---|---|
| Object Shapes | Supported | Supported |
| Inheritance Syntax | extends | Intersection (&) |
| Declaration Merging | Yes (Auto-merges) | No (Duplicate identifier error) |
| Unions & Primitives | No | Yes (`type Status = "ok" |
type User = {...} twice throws a duplicate identifier compiler error. Use interfaces when library authors need expandable shapes!Default to interface for OOP/library object shapes, and type for unions and utility types. Next, let's explore Union Types and Type Narrowing!