TypeScript theorytheory 0/50 · 0%
Types · hard

45. Advanced generics: default & multiple constraints

Giving generics sensible defaults and combining constraints.

Generic parameters can have default types (used when not explicitly specified or inferable) and can be constrained by an intersection of requirements.

ts
interface Identifiable { id: string; }
interface Timestamped { createdAt: number; }

function stamp<T extends Identifiable & Timestamped>(item: T): string {
  return `${item.id}@${item.createdAt}`;
}

interface ApiResponse<T = unknown> {
  data: T;
  status: number;
}

const raw: ApiResponse = { data: "anything", status: 200 }; // T defaults to unknown
const typed: ApiResponse<{ balance: number }> = { data: { balance: 5 }, status: 200 };

Combined constraints (`T extends A & B`) require the argument to satisfy every listed requirement simultaneously. Defaults are especially handy for library APIs where most callers don't care about the generic parameter but power users can still supply one.

Check your understanding

  1. 1. What does `T extends Identifiable & Timestamped` require of T?

  2. 2. What happens when `ApiResponse` is used without a type argument, given `interface ApiResponse<T = unknown>`?

  3. 3. Why are default generic parameters useful for library APIs?