thecodex.expert · The Codex Family of Knowledge
TypeScript

Interfaces vs Types

Declare the same interface name twice, and TypeScript merges them into one — try that with type, and it’s a compile error every time.

TypeScript 6.0 interface can merge; type can’t Last verified:
Canonical Definition

Both interface and type describe an object's shape, and for most everyday use they're interchangeable — a value satisfying one will satisfy the equivalent other. The genuine, load-bearing difference is declaration merging: multiple interface declarations with the same name automatically combine into one, which type aliases cannot do at all (redeclaring the same type name is a compile error). Conversely, only type can directly name a union, intersection, tuple, or primitive — interface is limited to object shapes.

Both describe an object shape, nearly identically

These two produce equivalent type-checking behavior — a value assignable to one is assignable to the other.

TypeScriptequivalent.ts
interface UserI {
    name: string;
    age: number;
}

type UserT = {
    name: string;
    age: number;
};

const u1: UserI = { name: "Alice", age: 30 };   // fine
const u2: UserT = { name: "Bob", age: 25 };       // also fine

Declaration merging: only interface can do this

This is genuinely useful for extending a type defined elsewhere (a library's global types, for example) — and it's the one thing a type alias fundamentally cannot replicate.

TypeScriptdeclaration_merging.ts
interface Window {
    title: string;
}

interface Window {   // a SECOND declaration of the same name
    ts: number;
}

// they automatically merge into one interface with BOTH properties:
// interface Window { title: string; ts: number; }

// type Window = { title: string };
// type Window = { ts: number };   // COMPILE ERROR: Duplicate identifier 'Window'

Only type can name a union, intersection, or primitive

interface is restricted to describing object shapes — it cannot directly name a union of string literals, a primitive alias, or a tuple the way type can.

TypeScripttype_only.ts
type Status = "active" | "inactive";   // fine — type can name a union directly
// interface Status = "active" | "inactive";   // not valid syntax at all

type ID = string | number;               // fine
type Coordinates = [number, number];    // fine — a tuple

Sources

1
Microsoft. TypeScript Handbook, "Differences Between Type Aliases and Interfaces", typescriptlang.org/docs/handbook/2/everyday-types.html.