HardGeneric Constraints🐛 Debug Challenge

Missing extends object constraint — primitive passed to object utility

Buggy Code — Can you spot the issue?

// TypeScript without constraint: merge<T, U>(a: T, b: U): T & U
// Bug: works at type level but no constraint prevents primitives

function merge(a, b) {
  if (typeof a !== 'object' || a === null || typeof b !== 'object' || b === null) {
    // No TypeScript error without constraint — silently returns wrong type
    return String(a) + String(b); // treats as string concat when primitives
  }
  return { ...a, ...b };
}

// Correct usage: two objects
const combined = merge({ name: 'Alice' }, { age: 30 });
console.log(JSON.stringify(combined));

// Bug: passing primitives — TypeScript should reject with T extends object constraint
const wrong = merge('hello', 42);
console.log(wrong);
console.log(typeof wrong);

Fixed Code

// Fix: validate inputs are objects before merging
function merge(a, b) {
  if (typeof a !== 'object' || a === null) {
    throw new TypeError('First argument must be an object');
  }
  if (typeof b !== 'object' || b === null) {
    throw new TypeError('Second argument must be an object');
  }
  return { ...a, ...b };
}

// Correct usage only — TypeScript constraint prevents primitives at compile time
const combined = merge({ name: 'Alice' }, { age: 30 });
console.log(JSON.stringify(combined));

const full = merge({ id: 1, name: 'Alice' }, { role: 'admin', active: true });
console.log(full.name + ':' + full.role);

Bug Explained

Bug: Without T extends object constraint, TypeScript allows merging primitives. The function falls into the string concatenation branch and returns "hello42" — not an object merge. TypeScript fix: T extends object, U extends object.

Explanation: With proper inputs, spread merge works correctly. TypeScript's T extends object constraint prevents primitives at compile time — no need for runtime checks when types are enforced.

Key Insight: Constraints (T extends object) are compile-time guarantees. They prevent whole classes of misuse without runtime overhead. Always constrain generics to the minimum required interface — it documents intent AND prevents bugs.

More Generic Constraints Debug Challenges

MediumMissing keyof constraint — unsafe property accessHardGeneric function returns any instead of constrained type

Practice spotting bugs live →

38 debug challenges with AI hints

🐛 Try Debug Lab