Type vs Interface

intermediate type interface interview-favorite

This is THE TypeScript interview question. The honest answer: 90% of the time they’re interchangeable for object shapes, but the 10% matters.

In simple language — interface is built for describing the shape of an object. type is more flexible and can describe anything: objects, unions, primitives, tuples, function signatures.

What they have in common

Both describe object shapes. Both work with classes via implements. Both work with generics.

// Interface
interface User {
  id: number;
  name: string;
}

// Type alias — same job
type UserT = {
  id: number;
  name: string;
};

Where they differ

interface
✓ Object shapes
✓ extends (single + multiple)
✓ Declaration merging
✓ implements on classes
✗ Unions / intersections
✗ Primitives, tuples, mapped
type
✓ Object shapes
✓ & (intersection)
✓ | (union)
✓ Primitives, tuples, mapped
✓ Conditional & template literals
✗ Declaration merging

Declaration merging — interface only

Declare an interface twice and TS merges them. This is powerful for extending third-party types (e.g., adding properties to Window).

interface User { id: number; }
interface User { name: string; }

const u: User = { id: 1, name: "Manish" }; // both required ✅

With type, this is an error — types can’t be redeclared.

type UserT = { id: number; };
type UserT = { name: string; }; // ❌ Duplicate identifier

Unions — type only

type can describe anything; interface can only describe an object shape.

type ID = string | number;            // ✅ type can
type Result = { ok: true } | { ok: false; error: string };

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

Extending

Both can extend, just with different syntax.

// Interface extends interface
interface Animal { name: string; }
interface Dog extends Animal { breed: string; }

// Type uses intersection
type AnimalT = { name: string; };
type DogT = AnimalT & { breed: string; };

Implements (with classes)

Both work, no real difference here.

interface Logger { log(msg: string): void; }
class ConsoleLogger implements Logger {
  log(msg: string) { console.log(msg); }
}

The practical rule

  • Use interface for object shapes that are part of a public API. Declaration merging is a nice escape hatch.
  • Use type when you need unions, intersections, tuples, mapped types, or conditional types.
  • Be consistent within a codebase. Pick a default and stick with it.

A common convention: interface for object shapes, type for everything else.

Performance note

For very large unions, interface (with extends) is slightly faster for the compiler than type with intersection. Mostly irrelevant unless you’re typing thousands of objects.

Interview soundbite

“For plain object shapes they’re nearly identical. The differences: interface supports declaration merging and only describes objects; type is a general alias that can describe unions, primitives, tuples, and mapped types. Use interface for public object APIs, type for everything else.”