The type does not satisfy the constraint
If a generic parameter does not satisfy its constraint (extends), TypeScript produces a compile-time error - that is, the code will not compile until you substitute a matching type.
What "does not satisfy the constraint" means
When you write, for example:
function fn<T extends { id: number }>(value: T) { ... }you are telling TypeScript:
"Only allow types
Tthat must have a fieldid: number."
If you try to pass a type without id, the compiler will say: "Type X does not satisfy the constraint Y".
Example 1: An error on a constraint mismatch
function printId<T extends { id: number }>(obj: T) {
console.log(obj.id);
}
printId({ id: 42 }); // fits
printId({ name: "Tim" }); // Error:
// Argument of type '{ name: string }' is not assignable to parameter of type '{ id: number; }'.
Tmust be a subtype of{ id: number }, but{ name: string }does not fit.
Example 2: A mismatch with a union
function toStringValue<T extends string | number>(value: T): string {
return value.toString();
}
toStringValue("hello"); // ok
toStringValue(100); // ok
toStringValue(true); // Error: 'boolean' does not satisfy the constraint 'string | number'.The type
booleanis not part of the allowed set (string | number).
Example 3: A mismatch with a dependent parameter
function getProp<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}
const user = { id: 1, name: "Tim" };
getProp(user, "id"); // ok
getProp(user, "age"); // Error: Type '"age"' is not assignable to parameter of type '"id" | "name"'
Kmust be a key of the objectT, but"age"is not one.
Example 4: A mismatch with the object constraint
function logKeys<T extends object>(obj: T) {
console.log(Object.keys(obj));
}
logKeys({ a: 1 }); // ok
logKeys(42); // Error: number does not satisfy the constraint 'object'Primitives (
number,string,boolean) are not objects.
Example 5: A mismatch for classes (constructor constraints)
type Constructor<T> = new (...args: any[]) => T;
function createInstance<T extends Constructor<any>>(Ctor: T) {
return new Ctor();
}
class Person {}
createInstance(Person); // ok
createInstance(123); // Error: number does not satisfy the constraint 'new (...args: any[]) => any'
123is not a constructor, so it does not fit the constraint.
Example 6: An error from violating a template constraint
type Prefixed<T extends `id_${string}`> = { key: T };
const good: Prefixed<"id_123"> = { key: "id_123" }; // ok
const bad: Prefixed<"user_1"> = { key: "user_1" }; // Type '"user_1"' does not satisfy the constraint '`id_${string}`'
Tmust match the template stringid_....
What happens under the hood
When TypeScript sees T extends U, it checks:
Can the type
Tbe assigned to the typeU(isTassignable toU).
If not, a compile-time error:
Type 'T' does not satisfy the constraint 'U'.TypeScript does not try to automatically convert types - it simply disallows the mismatch.
An example with an explicit type
function identity<T extends number>(value: T) {
return value;
}
identity(42); // ok
identity<number>(42); // ok
identity<string>("hi"); // Type 'string' does not satisfy the constraint 'number'Even if you specify the generic explicitly, the compiler checks whether it fits the
extendsconstraint.
Why this is useful
- Type safety: you cannot accidentally pass an unsuitable type.
- Autocomplete: inside the function, TS knows which properties are guaranteed.
- Flexibility: you can set "soft" constraints (for example,
{ id: any }).
Summary
| Situation | Example | What happens |
|---|---|---|
| The type satisfies the constraint | <T extends { id: number }> + { id: 1 } | It works |
| The type is missing the needed properties | { name: string } | Error |
| The type is not part of the union | `<T extends string | number>+boolean` |
| The key does not exist | <K extends keyof T> + "age" | Error |
| The type is not an object | <T extends object> + number | Error |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.