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".
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 →