Type System

Interfaces and Types

Define the shape of objects using interfaces and type aliases for reusable, self-documenting code.

Interfaces

Interfaces define the shape of an object. They describe what properties an object should have and their types.

Type Aliases

Type aliases create a name for any type — not just objects. They're more flexible than interfaces.

Interface vs Type

Both are very similar. Key differences:

  • Interfaces can be extended and merged (declaration merging)
  • Type aliases can represent unions, intersections, and primitives
  • In most cases, either works — use whichever is clearer

Optional and Readonly Properties

  • ? makes a property optional
  • readonly prevents a property from being modified after creation

Example

typescript
// Interface
interface Product {
  id: number;
  name: string;
  price: number;
  description?: string; // optional
  readonly createdAt: Date; // can't be changed after creation
}

// Extending interfaces
interface DigitalProduct extends Product {
  downloadUrl: string;
  fileSize: number;
}

// Type alias
type Point = {
  x: number;
  y: number;
};

// Union type alias
type ID = string | number;

// Intersection types
type Employee = Person & { employeeId: number };

// Interface with methods
interface Repository<T> {
  findById(id: ID): T | undefined;
  findAll(): T[];
  save(item: T): void;
  delete(id: ID): void;
}

// Implementing an interface
class UserRepository implements Repository<User> {
  private users: User[] = [];

  findById(id: ID): User | undefined {
    return this.users.find(u => u.id === id);
  }

  findAll(): User[] {
    return this.users;
  }

  save(user: User): void {
    this.users.push(user);
  }

  delete(id: ID): void {
    this.users = this.users.filter(u => u.id !== id);
  }
}
Try it yourself — TYPESCRIPT