BeCuriouzBeCuriouz

Learn something new every day

🔷 TypeScript
📦

Generic Interfaces & Classes: Reusable Containers

💡 Attaching a <T> to an interface or class turns it into one reusable, type-safe blueprint that specializes to any concrete type on use.

In earlier cards you saw how a generic function captures a type with a parameter like . That same idea scales up: you can attach a type parameter to an entire interface or class, turning it into a reusable blueprint that works for any type while keeping full type safety.

A generic interface declares its type parameter right after the name. Here Box holds a value of whatever type you plug in — Box forces .value to be a number, Box forces a string:

ts
interface Box<T> {
  value: T;
}

const n: Box<number> = { value: 42 };
const s: Box<string> = { value: "hi" };

A generic class works the same way — the after the class name is in scope across every field and method, so the type flows through consistently:

ts
class Stack<T> {
  private items: T[] = [];
  push(item: T): void { this.items.push(item); }
  pop(): T | undefined { return this.items.pop(); }
}

const nums = new Stack<number>();
nums.push(10);        // ok
const top = nums.pop(); // top: number | undefined
// nums.push("oops");  // ✗ compile error

Because nums is a Stack, push only accepts numbers and pop returns number | undefined — no casting, no any. One definition, infinitely many concrete types.

📦 Generic Interfaces & Classes: Reusable Containers — BeCuriouz