Describe object shapes with interfaces — declaring them, extending them, and implementing them in classes.
Why: interfaces describe object shapes, support optional and readonly members, compose via extends, and double as contracts that classes implement.
interface User {
id: number;
name: string;
email?: string; // optional
readonly createdAt: Date; // immutable after creation
}
// extends — build on existing shapes
interface Admin extends User {
permissions: string[];
}
const admin: Admin = {
id: 1,
name: 'Alice',
createdAt: new Date(),
permissions: ['users:write'],
};
// admin.createdAt = new Date(); // Error: read-only
// Interfaces as contracts for classes
interface Serializable {
serialize(): string;
}
class Session implements Serializable {
constructor(private userId: number) {}
serialize() {
return JSON.stringify({ userId: this.userId });
}
}
console.log(admin.permissions, new Session(1).serialize());