intermediate

Generics and constraints

Preserve relationships between inputs and outputs while constraining required capabilities.

Generics describe relationships between values without erasing specific types. A generic identity keeps the same input and output type. Constraints with `extends` allow required operations while preserving the caller-specific shape.

					function getId<T extends { id: string }>(value: T): string {
  return value.id;
}
				

Use generics when the caller should get back information related to their input. A generic that appears only once is often unnecessary. Overly broad constraints lose safety; overly narrow ones make helpers unusable.

On interviews: contrast `<T>` with `unknown` and explain when inference should do the work.

Common pitfalls: mixing similar APIs and forgetting edge cases during live coding.

The trade-off is often clarity versus safety or expressiveness versus maintainability. Checklist:

  • Preserve input-output relationships.
  • Constrain required operations only.
  • Let inference work when possible.