HardGeneric Constraints🐛 Debug Challenge

Generic function returns any instead of constrained type

Buggy Code — Can you spot the issue?

// Bug: returns any[] — TypeScript loses type information
// Should be: function filterDefined<T>(arr: (T | null | undefined)[]): T[]

function filterDefined(arr) {
  // Returns filtered array but type is lost — TypeScript sees any[]
  return arr.filter(item => item !== null && item !== undefined);
}

const maybeNumbers = [1, null, 3, undefined, 5];
const result = filterDefined(maybeNumbers);

// Bug: without proper typing, TypeScript allows incorrect method calls
// result is inferred as any[] — no type safety on elements
console.log(result.join(','));

// TypeScript with proper return type would infer result as number[]
// and result[0].toFixed(2) would be safe without assertion
const first = result[0];
console.log(typeof first);
console.log(result.length);

Fixed Code

// Fix: use type predicate to preserve generic type information
// TypeScript: function filterDefined<T>(arr: (T | null | undefined)[]): T[]

function filterDefined(arr) {
  return arr.filter(item => item !== null && item !== undefined);
}

// TypeScript fix would use type predicate:
// (item): item is T => item !== null && item !== undefined

const maybeNumbers = [1, null, 3, undefined, 5];
const result = filterDefined(maybeNumbers);

// With proper typing, result would be number[] — all operations safe
const doubled = result.map(n => n * 2);
console.log(doubled.join(','));

const first = result[0];
console.log(typeof first);
console.log(result.length);

Bug Explained

Bug: filterDefined returns any[] (or inferrred loosely) instead of T[]. TypeScript loses knowledge that elements are numbers after filtering. The fix requires an explicit generic return type annotation and/or a type predicate.

Explanation: filterDefined correctly removes null and undefined values — result has 3 elements [1, 3, 5]. doubled maps each by 2. TypeScript with proper return type T[] would know all elements are numbers.

Key Insight: Type predicates (item is T) in filter callbacks tell TypeScript to narrow the array element type. (arr: (T|null|undefined)[]).filter((x): x is T => x != null) returns T[] — not (T|null|undefined)[].

More Generic Constraints Debug Challenges

MediumMissing keyof constraint — unsafe property accessHardMissing extends object constraint — primitive passed to object utility

Practice spotting bugs live →

38 debug challenges with AI hints

🐛 Try Debug Lab