← Back to TypeScript Course | Chapter 7: Generics | Lesson 4 of 8

Generic Classes

Generic classes use type parameters to create reusable classes that work with different data types. The class can preserve the type of values stored and returned by its methods.
Syntax
typescript
class ClassName<T> {
  property: T;
  constructor(value: T) {
    this.property = value;
  }
}

Basic Generic Class

A class can declare a type parameter and use it for its properties and methods, so the same class definition produces objects specialized to whatever type is supplied when it's instantiated.

Example: Basic Generic Class

typescript
class Box<T> {
  constructor(public value: T) {}
}
const box = new Box<string>("hello");
console.log(box.value);

Generic Stack

A generic class can implement reusable data structures such as a stack or queue while preserving the exact type of the items stored inside, instead of falling back to any and losing type safety on every read.

Example: Generic Stack

typescript
class Stack<T> {
  private items: T[] = [];
  push(item: T) { this.items.push(item); }
  pop(): T | undefined { return this.items.pop(); }
}
const stack = new Stack<number>();
stack.push(1);
stack.push(2);
console.log(stack.pop());

Generic Class Methods

Methods inside a generic class can use the class's own type parameter for consistent input and output typing, so operations like push and pop on a generic Stack<T> always agree on what type T is.

Example: Generic Class Methods

typescript
class Stack<T> {
  private items: T[] = [];
  push(item: T): void { this.items.push(item); }
  peek(): T { return this.items[this.items.length - 1]; }
}
const s = new Stack<string>();
s.push("top");
console.log(s.peek());

Generic Classes with Objects

Generic classes can store complex object types by using a type alias or interface as the type argument, which works exactly the same way as supplying a simple type like number or string.

Example: Generic Classes with Objects

typescript
interface User { name: string; }
class Repository<T> {
  private items: T[] = [];
  add(item: T) { this.items.push(item); }
  all(): T[] { return this.items; }
}
const users = new Repository<User>();
users.add({ name: "Farhan" });
console.log(users.all());

Type Inference in Generic Classes

TypeScript can often infer a class's type parameter directly from the constructor arguments passed to new, so callers don't always have to write the type argument explicitly.

Example: Type Inference in Generic Classes

typescript
class Box<T> {
  constructor(public value: T) {}
}
const box = new Box(123); // T inferred as number
console.log(box.value);
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. Forgetting the type argument, as in new Stack(), so the type becomes unknown or is inferred too loosely.
  2. Using the class type parameter in a static member, like static create(x: T), when statics cannot reference T.
  3. Popping from an empty Stack<T> and using the result without checking, since pop() returns T | undefined.
🔒

Chapter Quiz — Complete all 8 topics to unlock

0/8 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.