interface vs type — Choosing Well

Two ways to name an object shape, with real differences once you push on them.

For a plain object shape, interface and type are almost interchangeable, and either is fine. The differences show up at the edges, and knowing them lets you choose with intent rather than habit.

Capabilityinterfacetype
Object shapesYesYes
Unions / tuples / primitivesNoYes
Declaration mergingYesNo
extends / & compositionextends& intersection
Mapped & conditional typesNoYes
interface Point { x: number; y: number }
type ID = string | number;        // only type can do this
type Pair = [number, number];     // and this

A workable rule

Use interface for public object shapes and anything a class will implement or that a library might extend. Use type for unions, tuples, function types, and anything computed with mapped or conditional types.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • A library author uses interface for public API contracts because consumers can extend them via declaration merging.
  • A developer uses a type alias for a complex union or tuple type that cannot be expressed with interface syntax.
  • A team adopts interface for object shapes and type for computed or conditional types to keep conventions consistent.

More examples

Declaration merging with interface

Two interface declarations with the same name merge their members — a feature unique to interfaces, unavailable with type.

Example · ts
interface Window {
  myPlugin: { version: string };
}
// Two declarations of the same interface merge automatically
interface Window {
  otherProp: number;
}
// Window now has both myPlugin and otherProp

Union type — only with type

Union types must be declared with type; interfaces cannot represent unions, making type the required choice here.

Example · ts
// Only type aliases support union types
type ID = string | number;
type NullableString = string | null;

// interface ID = string | number; // syntax error

Extending — interface and type

Both interface extends and type intersection compose types, but the syntax and some edge-case semantics differ.

Example · ts
interface Named { name: string; }
interface Aged extends Named { age: number; }   // interface extends

type Tagged = Named & { tag: string };          // type intersection

const a: Aged  = { name: 'Alice', age: 30 };
const b: Tagged = { name: 'Bob', tag: 'admin' };

Discussion

  • Be the first to comment on this lesson.
interface vs type — Choosing Well — TypeScript | SoundsCode