Hint
Generic defaults (T = SomeType) kick in when the type parameter cannot be inferred AND is not explicitly provided. The constraint (T extends object) applies regardless of whether a default is used.
// Simulate generic with constraint and default
// function wrap<T extends object = Record<string, unknown>>(val: T): { wrapped: T }
function wrap(val) {
return { wrapped: val };
}
// Explicit type arg — T = { name: string }
const a = wrap({ name: 'Alice' });
// T[wrapped] = { name: string }
// Inferred from arg — T = { id: number, active: boolean }
const b = wrap({ id: 1, active: true });
// Default would apply when called with no args (not possible here)
// but T extends object means: numbers/strings rejected at type level
console.log(JSON.stringify(a));
console.log(JSON.stringify(b));
console.log(typeof a.wrapped);
console.log(Object.keys(b.wrapped).sort().join(','));{"wrapped":{"name":"Alice"}}
{"wrapped":{"id":1,"active":true}}
object
active,idExplanation: wrap infers T from the argument. a.wrapped is { name: "Alice" }, b.wrapped is { id: number; active: boolean }. TypeScript would reject non-object arguments due to the T extends object constraint.
Key Insight: Generic defaults (T = SomeType) kick in when the type parameter cannot be inferred AND is not explicitly provided. The constraint (T extends object) applies regardless of whether a default is used.