Generic Classes

A Class That's Parameterized by a Type

Generic Classes

Classes can take type parameters. Useful for containers, stacks, queues — anything that holds "things of T".

3 min read Level 2/5 #typescript#generics#classes
What you'll learn
  • Author a generic class
  • Use generic methods
  • Recognize the inference at construction

A class can take type parameters. The parameter is in scope for all methods, properties, and this.

A Tiny Stack

class Stack<T> {
  private items: T[] = [];

  push(item: T): void {
    this.items.push(item);
  }

  pop(): T | undefined {
    return this.items.pop();
  }

  peek(): T | undefined {
    return this.items[this.items.length - 1];
  }

  get size(): number {
    return this.items.length;
  }
}

const s = new Stack<number>();
s.push(1);
s.push(2);
s.pop();   // number | undefined

Stack<number> is a stack of numbers. Push, pop, peek — all type-safe.

Inference at Construction

If a constructor parameter uses T, TS can infer:

class Box<T> {
  constructor(public value: T) {}
}

const a = new Box(42);          // Box<number>
const b = new Box("hello");     // Box<string>
const c = new Box<User>({ id: "1", name: "Ada" });

public value: T is parameter-property shorthand (covered in the OOP chapter).

Methods Can Add Type Parameters Too

class List<T> {
  items: T[] = [];

  map<U>(fn: (item: T) => U): U[] {
    return this.items.map(fn);
  }
}

const list = new List<number>();
const names = list.map(n => `n=${n}`);   // string[]

The class has <T>; the method adds <U>.

Generic Class With Constraints

class Sortable<T extends { compareTo(other: T): number }> {
  items: T[] = [];

  add(item: T) { this.items.push(item); }
  sort() { this.items.sort((a, b) => a.compareTo(b)); }
}

Restrict T to types that have a specific shape.

Up Next

Generic utility functions — building your own helpers.

Generic Utilities →