Easy10 minType Systems

interface vs type

Structural vs Nominal Typing

Why This Is Asked

This is a quick litmus test for TypeScript experience. Interviewers want to see if you know the practical differences — especially declaration merging — and have a reasoned opinion on when to use each, rather than just a default preference.

Key Concepts

  • interface supports declaration merging (defining the same interface twice merges them), type does not
  • type can represent unions, intersections, tuples, mapped types, and primitives; interface cannot
  • Both can describe object shapes and be extended (interface via extends, type via &)
  • interface is generally preferred for public API contracts and library definitions (mergeability)
  • type is preferred for complex type operations, utility types, and union/intersection patterns

Answers by Technology

+ Add Variant
TypeScriptImprove this answer ✏️

Expected Answer

Both interface and type can describe object shapes, but they differ in capabilities and intended use.

Interface

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

// Declaration merging — same interface defined twice is merged
interface User {
  email: string;
}
// User now has id, name, AND email

// Extension
interface Admin extends User {
  role: 'admin';
}

Type Alias

// Unions — interfaces can't do this
type Result = Success | Error;

// Tuples
type Point = [number, number];

// Mapped types
type Readonly<T> = { readonly [K in keyof T]: T[K] };

// Intersection (similar to extends)
type Admin = User & { role: 'admin' };

When to Use Each

Use interface when… Use type when…
Defining object shapes for public APIs Defining unions or intersections
You need declaration merging (e.g., augmenting library types) Working with tuples, primitives, or mapped types
You want extends for clear hierarchies Building utility types or conditional types

The Key Difference: Declaration Merging

This is the most practical difference. Libraries like express or jest expose interfaces so consumers can augment them:

// Augmenting Express Request in your app
declare module 'express' {
  interface Request {
    user?: AuthUser;
  }
}

This is impossible with type — redefining a type alias is a compile error.

Common Mistakes

  • “Always use interface”: A common cargo-cult rule. type is necessary for unions, mapped types, and conditional types — which are used heavily in real TypeScript codebases.
  • “Always use type”: Loses the ability to leverage declaration merging, which is essential when augmenting third-party library types.
  • Confusing extends with &: They behave similarly for simple cases, but extends gives better error messages for incompatible types, while & silently creates never for conflicting properties.

Follow-up Questions

  • What happens when you intersect two types with conflicting properties? (Answer: The property type becomes never. For example, { x: string } & { x: number } gives x: never, which makes the type unusable).
  • Can a class implement a type alias? (Answer: Yes, as long as the type describes an object shape. class Foo implements MyType {} works for object types but not for unions or primitives).