Lesson 19 / 26

Generic Interfaces, Classes & Constraints

Generic containers, and limiting T to types with certain properties.

Generic interface & class

A generic class or interface reuses one definition for many payload types — a Box<string> and a Box<number> share the same shape.

interface Box<T> {
  value: T;
}

class Container<T> {
  constructor(public value: T) {}
  get(): T {
    return this.value;
  }
}

const c = new Container<number>(42);

Constraining with extends

T extends { length: number } limits T to types that at least have a length property — narrower than "anything", wide enough to be reusable.

function logLength<T extends { length: number }>(item: T): void {
  console.log(item.length);
}

logLength("hello");     // OK, strings have length
logLength([1, 2, 3]);   // OK, arrays have length
logLength(42);
// Error: Argument of type 'number' is not assignable to parameter of type '{ length: number }'.

Name generics meaningfully

T is fine for one generic. With several, prefer readable names — TKey, TValue — over T, U, V.