MediumClass Patterns🐛 Debug Challenge

Abstract class instantiated directly — unexpected behavior

Buggy Code — Can you spot the issue?

// TypeScript: Cannot create an instance of an abstract class
// Bug: Base class without concrete implementation is used directly

class Repository {
  tableName;

  constructor(tableName) {
    this.tableName = tableName;
  }

  // Should be abstract — no implementation in base class
  findAll() {
    // Returns undefined — no implementation
  }

  findById(id) {
    // Returns undefined — no implementation
  }
}

// Bug: instantiated directly instead of through a concrete subclass
const repo = new Repository('users');

const all = repo.findAll();
console.log(all);           // undefined — base class has no data
console.log(typeof all);

Fixed Code

class Repository {
  tableName;
  // In TypeScript, mark as abstract class — cannot be instantiated

  constructor(tableName) {
    this.tableName = tableName;
  }

  // Abstract methods — must be implemented by subclasses
  findAll() { return []; } // base fallback for JS demo
  findById(id) { return null; }
}

// Concrete subclass — provides real implementation
class UserRepository extends Repository {
  #data;

  constructor() {
    super('users');
    this.#data = [
      { id: 1, name: 'Alice' },
      { id: 2, name: 'Bob' },
    ];
  }

  findAll() {
    return this.#data;
  }

  findById(id) {
    return this.#data.find(u => u.id === id) || null;
  }
}

const repo = new UserRepository();

const all = repo.findAll();
console.log(all.length);
console.log(all[0].name);

Bug Explained

Bug: Repository should be abstract. Instantiating it directly gives a useless object where all methods return undefined. TypeScript's abstract class prevents this: "Cannot create an instance of an abstract class."

Explanation: UserRepository extends the base and provides concrete implementations. findAll() returns the actual data. TypeScript abstract classes prevent instantiating the base and force subclasses to implement abstract methods.

Key Insight: Abstract classes define contracts + shared behavior. Mark methods abstract when they must be overridden, and concrete when they provide a default implementation. TypeScript enforces at compile time that abstract methods are implemented.

More Class Patterns Debug Challenges

MediumPrivate field accessed outside class — wrong data exposedHardClass missing interface implementation — methods silently absent

Practice spotting bugs live →

38 debug challenges with AI hints

🐛 Try Debug Lab