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.