Abstract Classes and implements

Introduction

Not every class should be instantiated directly. Abstract classes define shared behavior and leave specific pieces to subclasses. implements connects classes (and sometimes other patterns) to interface contracts so callers depend on capabilities, not concrete types. This chapter ties object-oriented structure to TypeScript’s type checking.

Prerequisites

abstract Classes and Methods

Mark a class abstract when it is a base, not a complete implementation:

typescript
abstract class Notification {
  constructor(public recipient: string) {}
 
  abstract render(): string;
 
  send(): void {
    const body = this.render();
    console.log(`To: ${this.recipient}\n${body}`);
  }
}

Code explanation:

  • abstract render() must be implemented by concrete subclasses
  • send() is concrete shared logic using render()

Concrete subclass:

You cannot instantiate the abstract base:

typescript
// const n = new Notification("x");  // Error: Cannot create an instance of an abstract class

abstract vs interface

abstract classinterface
RuntimeEmits JavaScript classErased—no runtime
ImplementationCan include concrete methods and fieldsOnly shape—no method bodies
InheritanceSingle extends chainMultiple implements
Use whenShared code + template method patternPure contracts, multiple roles
typescript
interface Serializable {
  toJSON(): string;
}
 
abstract class Model implements Serializable {
  abstract id: string;
 
  toJSON(): string {
    return JSON.stringify({ id: this.id });
  }
}

Code explanation:

  • Model provides default toJSON while forcing subclasses to define id
  • implements Serializable documents the capability for type checkers

implements Multiple Interfaces

Every interface member must be present with compatible types.

Structuring a Small Hierarchy

Code explanation:

  • charge is the template; process is the hook subclasses customize
  • Return type Promise<{ ok: boolean }> documents async behavior

When to Prefer interface Only

Use interfaces (no abstract class) when:

  • You only need a shape, no shared implementation
  • Multiple unrelated classes must satisfy the same contract
  • You want to avoid inheritance depth

Functions depend on Logger, not a specific class.

implements with Generics (Preview)

Comparable<Version> keeps comparisons type-safe.

Common Mistakes

MistakeResultFix
Forget super() in subclassError in constructorCall super(...) first
Leave abstract method unimplementedClass stays abstract / errorImplement all abstract members
implements without matching typesCompile errorsAlign method signatures
Deep inheritance treesHard to changeFavor composition + interfaces

FAQ

Can an abstract class implement an interface?

Yes. abstract class X implements Y is common for shared defaults plus a contract.

Can interfaces extend abstract classes?

No. Interfaces extend other interfaces (or use extends with object types). Classes extend abstract classes.

abstract methods in interfaces?

Interfaces can declare method signatures without bodies—similar idea, different syntax. Use interface for pure contracts; abstract class when sharing code.

Multiple inheritance?

TypeScript allows one extends and multiple implements. No multiple class extension.

Are abstract classes used in React?

Function components dominate; classes appear in older code and some libraries. Understanding them still matters for Node services and domain models.

Should I mark every base class abstract?

Only when instantiation would be wrong or incomplete. Otherwise a normal class is fine.