JS Guide
HomeQuestionsTopicsCompaniesResources
BookmarksSearch

Built for developers preparing for JavaScript, React & TypeScript interviews.

ResourcesQuestionsSupport
HomeQuestionsSearchProgress
HomeTopicstypescriptInterfaces vs Type Aliases
PrevNext
typescript
beginner
8 min read

Interfaces vs Type Aliases

declaration-merging
extends
interfaces
objects
structural-typing
type-aliases
types

Interfaces define object shapes and can be extended with extends or merged via declaration merging — type aliases can represent any type (unions, tuples, primitives) but can't be merged, and the practical rule is to use interface for objects and type for everything else.

Key Points

1Interfaces for Objects

Define object shapes with optional (?), readonly, and index signatures. Support extends for composition and implements for class contracts.

2Type Aliases for Everything

Can represent any type — unions, intersections, tuples, primitives, function types. Cannot be declaration-merged.

3Declaration Merging

Same-name interfaces auto-merge their members — enables augmenting built-in types and third-party libraries. Type aliases cannot merge.

4extends vs Intersection

Interface extends catches property conflicts at the declaration. Type intersection (&) silently produces never for conflicts, causing subtle bugs.

5Practical Rule

Use interface for object shapes and public APIs. Use type for unions, tuples, and computed types. Both are structurally typed.

What You'll Learn

  • Explain the differences between interfaces and type aliases in TypeScript
  • Know when to use interface vs type alias based on the use case
  • Understand declaration merging and why it matters for library types
  • Compare extends (interface) vs intersection (&) for type composition

Deep Dive

Interfaces and type aliases are the two primary ways to name types in TypeScript. They overlap significantly for object types but have distinct capabilities.

Interfaces

Interfaces define the shape of an object — what properties it has and their types:

TypeScript
interface User {
  id: number;
  name: string;
  email: string;
  age?: number;          // optional property
  readonly createdAt: Date; // can't be reassigned
}

Optional properties (?) can be undefined or absent. Readonly properties can be set during creation but not reassigned afterward.

Type Aliases

Type aliases create a name for any type — not just objects:

TypeScript
type ID = string | number;
type Point = [number, number];
type Callback = (data: string) => void;
type User = { id: number; name: string; };

Type aliases can represent unions, intersections, tuples, primitives, function types, and mapped types. Interfaces can only describe object shapes.

Interface extends vs Type Intersection

Both can compose types, but the syntax differs:

TypeScript
// Interface extension
interface Animal { name: string; }
interface Dog extends Animal { breed: string; }
 
// Type intersection
type Animal = { name: string; };
type Dog = Animal & { breed: string; };

Interface extends checks for conflicts — if Dog tries to override a property from Animal with an incompatible type, TypeScript errors. Type intersections (&) silently create a never type for conflicting properties, which causes hard-to-debug errors later.

Declaration Merging

Interfaces with the same name in the same scope automatically merge their members:

TypeScript
interface Window { customProp: string; }
// Merges with the built-in Window interface

This is how TypeScript's built-in types work — Array, Promise, and DOM types are assembled from multiple interface declarations across different .d.ts files. Module augmentation relies on declaration merging.

Type aliases cannot be merged — redeclaring a type alias with the same name is a compile error.

implements

Classes can implement interfaces, creating a contract that the class must satisfy:

TypeScript
interface Serializable { serialize(): string; }
class User implements Serializable {
  serialize() { return JSON.stringify(this); }
}

Classes can also implement type aliases (if the type describes an object shape), but interface implements is the conventional pattern.

Index Signatures

Both interfaces and types support index signatures for dynamic property names:

TypeScript
interface Dictionary { [key: string]: string; }
interface Config { [key: string]: unknown; port: number; } // port must be compatible

When to Use Which

The TypeScript community has converged on a practical rule:

  • interface for object shapes — especially public APIs, class contracts, and anything that might need declaration merging
  • type for unions, tuples, mapped types, and any non-object type

For object types specifically, both work. The TypeScript compiler internally optimizes interface checking slightly better than type alias objects, but the difference is negligible in practice. The real distinction is declaration merging (interface only) and ability to represent non-object types (type alias only).

Key Interview Distinction

Interfaces define object shapes with extends for composition and declaration merging for augmentation. Type aliases can represent any type (unions, tuples, primitives). Interface extends catches conflicts; type intersections can silently create never types. Use interface for objects and public APIs; use type for unions, tuples, and computed types. Both are structurally typed — a value matches if it has the right shape, regardless of which name was used.

Fun Fact

The interface vs type debate is one of the longest-running discussions in the TypeScript community. The TypeScript handbook originally recommended interfaces for everything, then switched to recommending type aliases, then settled on 'use interface for objects, type for other things.' The TypeScript team internally uses a mix of both — there's no single correct answer.

Learn These First

Basic Types

beginner

Continue Learning

Generics

intermediate

Declaration Files

advanced

Practice What You Learned

What is the difference between interfaces and type aliases in TypeScript?
junior
interfaces
Both define object shapes, but interfaces can be extended and merged (declaration merging), while type aliases can represent unions, tuples, and primitives. Use interfaces for objects/classes and type aliases for unions or complex types.
Previous
Generics
Next
Mapped Types
PrevNext