T extends U Generic Constraints
Last updated: 2026-10-22
T extends U Generic Constraints
A constraint (extends) bounds a type parameter: <T extends HasId> promises "T has at least id: number". Within the constraint you may freely access T's members; outside it (passing a string) is rejected at compile time — safer than any, more flexible than a concrete type.
| Group | Generics |
|---|---|
| Kind | Syntax |
| Strict mode | Not required |
ℹ️ Info The editor transpiles TypeScript to JavaScript and runs it (no type checking); see each example's Output for type-check results.
📝 Syntax
interface HasId {
id: number;
}
function findById<T extends HasId>(items: T[], id: number): T | undefined {
return items.find((item) => item.id === id);
}
⚙️ Parameters
| T extends HasId | The constraint: the argument type must be compatible with HasId (at least id: number) |
|---|---|
| T | undefined | The return keeps the argument's exact shape: what you pass in is what you get back |
Returns:Same as unconstrained generics — the argument's precise type is preserved; the difference is that more members of T become usable inside the body.
▶ Example
Edit the code below and click Try it to see the transpiled result:
Output:
Desk
not found
(Runtime output after transpilation; extra fields on the products are fine — structural typing only checks the constraint's members)
💡 Notes
ℹ️ Info A constraint does not demand equality: { id: 1, name: "Lamp", price: 59 } stays compatible despite extra fields — structural typing only checks the required members.
💡 Tip Inline constraints skip the intermediate interface: function sumLengths<T extends { length: number }>(a: T, b: T) says "anything with length"; promote to an interface only when it grows complex.
⚠️ Note A constraint is a floor: T extends HasId guarantees id only; item.name is still unknown to the compiler unless you constrain it too.
🏷️ Related Generics
💡 Related cases
More cases coming soon.
📚 Related tutorials
❓ FAQ
Q Can constraints and defaults be combined?
A Yes, commonly: <T extends HasId = User> — User by default, any HasId-compatible type when given. The default must satisfy the constraint.
Q How do you constrain to a few literal values?
A With a literal union: function set<K extends "light" | "dark">(theme: K). K narrows to the literals; anything else is a compile error.
Q How do type parameters constrain each other?
A Reference an earlier one: <K extends keyof T> — K's range is determined by T, the core keyof pattern that keeps keys matched to the real object.