HomeGuidesTypeScriptTypeScript Types vs Interfaces — When to Use Which
🔷 TypeScript

TypeScript Types and Interfaces

Types and interfaces are the foundation of TypeScript. Here's what exams test — the differences and when each applies.

Examifyr·2026·6 min read

Type aliases

A type alias creates a name for any type — primitives, objects, unions, intersections, and more.

// Primitive alias
type UserId = string;
type Age = number;

// Object type
type User = {
    id: UserId;
    name: string;
    age: Age;
    email?: string;  // optional property
    readonly createdAt: Date;  // can't be changed after assignment
};

// Union type
type Status = 'active' | 'inactive' | 'pending';

// Function type
type Formatter = (value: string) => string;

Interfaces

Interfaces define object shapes. They support declaration merging — you can add properties in separate declarations.

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

// Extending an interface
interface AdminUser extends User {
    role: 'admin';
    permissions: string[];
}

// Declaration merging (unique to interfaces)
interface User {
    email: string;  // merged with the previous User interface
}

// Implementing an interface in a class
class UserService implements User {
    id = '1';
    name = 'Alice';
    email = '[email protected]';
}

Type alias vs interface — key differences

Both describe object shapes, but they have important differences.

// 1. type can represent unions; interface cannot
type StringOrNumber = string | number;  // OK
interface StringOrNumber = string | number;  // ERROR

// 2. Interfaces support declaration merging; types don't
interface Theme { color: string; }
interface Theme { spacing: number; }  // merged — valid
type Theme = { color: string; };
type Theme = { spacing: number; };  // ERROR: duplicate identifier

// 3. Both support extension, different syntax
type Extended = BaseType & { extra: boolean };  // intersection
interface Extended extends BaseInterface { extra: boolean; }

// Rule of thumb:
// Use interface for object shapes and classes
// Use type for unions, intersections, and primitives
Note: In modern TypeScript, both work for most object shapes. The Airbnb and common community style: prefer interface for public APIs (it's extensible), type for everything else.

Optional and readonly properties

Optional properties may be undefined. Readonly prevents reassignment after initialisation.

interface Config {
    readonly apiUrl: string;  // cannot be changed
    timeout?: number;         // may be undefined
    retries: number;          // required
}

const config: Config = { apiUrl: 'https://api.com', retries: 3 };
config.apiUrl = 'new';  // Error: readonly
config.timeout = 5000;  // OK: it's optional but can be set

// Readonly array
const ids: ReadonlyArray<number> = [1, 2, 3];
ids.push(4);  // Error: no push on ReadonlyArray

Exam tip

The most common TypeScript interview question: "Type vs interface — what's the difference?" — interface supports declaration merging and is preferred for class contracts; type supports unions/intersections and is more flexible. For plain object shapes, they're largely interchangeable.

🎯

Think you're ready? Prove it.

Take the free TypeScript readiness test. Get a score, topic breakdown, and your exact weak areas.

Take the free TypeScript test →

Free · No sign-up · Instant results

Next →
TypeScript Type Inference Explained — When to Add Type Annotations
← All TypeScript guides