Pick the right construct to model and compose your object types without duplicating code.
Open this lesson in KodokonYou already know how to declare object types. The real question on a project is choosing between type and interface, then composing existing types without duplicating code. Let's start with the most common scenario: modeling entities that look alike.
interface User {
id: number;
name: string;
}
interface Admin extends User {
permissions: string[];
}
const admin: Admin = {
id: 1,
name: "Ada",
permissions: ["users:write"],
};extends creates a clear relationship: an Admin is a User with extra powers. With a type alias, you get the same result through the intersection operator &, which merges several shapes into one. It's the perfect tool for cross-cutting concerns, like timestamps present on all your entities.
type Timestamps = {
createdAt: Date;
updatedAt: Date;
};
type Product = {
id: number;
label: string;
};
type StoredProduct = Product & Timestamps;So which one should you choose? Two differences really matter. First, only type can name a union like 'active' | 'archived'. Second, two interface declarations sharing the same name merge automatically: handy for augmenting a library's types, dangerous when it happens by accident.
type Status = "active" | "archived";
interface Config {
locale: string;
}
interface Config {
debug: boolean;
}
const config: Config = { locale: "fr", debug: true };