← Back to TypeScript Course | Chapter 23: Performance and Best Practices | Lesson 5 of 7

Interface vs Type Alias When to Use

Interfaces and type aliases can both describe object shapes, but they have different strengths. Interfaces are often convenient for extendable object contracts, while type aliases are especially useful for unions, tuples, and type composition.
Syntax
typescript
interface InterfaceName {
    property: type;
}

type AliasName = TypeA | TypeB;   // unions and intersections need type

Interfaces for Object Contracts

Interfaces are the natural choice for describing the shape of an object or the public API of a class, because they support declaration merging and read clearly as a contract other code implements.

Example: Interfaces for Object Contracts

typescript
interface User {
  name: string;
  age: number;
}
const u: User = { name: "Ravi", age: 25 };
console.log(u);

Type Aliases for Unions

Type aliases are the better fit once you need to name a union or intersection, since interfaces can only describe a single object shape and can't express "one of these several types."

Example: Type Aliases for Unions

typescript
type Status = "pending" | "done" | "failed";
const s: Status = "pending";
console.log(s);

Extending and Composing Types

Both interfaces and type aliases support extending other shapes, but interfaces use extends and can merge multiple declarations of the same name, while type aliases combine shapes with the & intersection operator instead.

Example: Extending and Composing Types

typescript
interface Base { id: number; }
interface User extends Base { name: string; }
type Tagged = Base & { tag: string };
const u: User = { id: 1, name: "Ravi" };
console.log(u);

Tuples and Function Types

Type aliases can name a tuple's fixed-length, fixed-position shape or a function's call signature directly, which reads more naturally than wrapping either in an interface.

Example: Tuples and Function Types

typescript
type Point = [number, number];
type Callback = (value: number) => void;
const p: Point = [1, 2];
const log: Callback = (v) => console.log(v);
log(p[0]);

Practical Selection Rules

As a rule of thumb: reach for an interface when modeling an object or class shape that might be extended later, and reach for a type alias for unions, tuples, primitives, or anything that isn't a plain object contract.

Example: Practical Selection Rules

typescript
interface User { name: string; } // object contract -> interface
type Id = string | number;        // union -> type alias
const u: User = { name: "Ravi" };
const id: Id = 42;
console.log(u, id);
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Trying to write a union with an interface, like interface Status = "a" | "b", which is a syntax error, since unions need type.
  2. Declaring two type aliases with the same name and expecting them to merge as interfaces do.
  3. Mixing interface and type for similar objects across a project without a consistent rule.
🔒

Chapter Quiz — Complete all 7 topics to unlock

0/7 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.