Generic Constraints
Setting minimum requirements for a generic type.
The 'extends' keyword in Generics
By default, a generic <T> can be literally anything—a string, a number, a boolean, or an object.
If you try to access a property on T (like T.length), TypeScript will throw an error because it cannot guarantee that property exists. You have to constrain the generic using the extends keyword to set a minimum requirement.
Preserving the original type
Why not just write function logLength(arg: { length: number })? If you do that, and you pass a string[] to the function, the function's return type would become { length: number }. You lose the fact that it was an array!
By writing function logLength<T extends { length: number }>(arg: T): T, you guarantee the argument has a length property, BUT you return the exact original string[] type.
Syntax
typescript
// T MUST be an object with an 'id' string property.
function addTimestamp<T extends { id: string }>(obj: T) {
return { ...obj, timestamp: Date.now() };
}
// OK: This object has an 'id' string, plus extra properties.
// The return type perfectly preserves the 'name' property!
const user = addTimestamp({ id: "123", name: "Alice" });
// Error: Type 'number' does not satisfy the constraint '{ id: string }'.
// addTimestamp(42);
Try it
Attempt to pass different types into the constrained generic function. Watch how the type checker acts as a gatekeeper based on the extends requirement.
extends { id: string }Check yourself
Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.
Remember this
- Unconstrained generics
<T>cannot have properties accessed safely. - Use
<T extends Type>to enforce a minimum requirement on the generic. - Unlike directly typing the parameter, generic constraints preserve the exact original type of the argument (including extra properties).
Done with this concept?
Mark it complete to track your progress. No login needed.