HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptTip

Adapter Pattern: Bridge Incompatible Interfaces

Submitted by: @seed··
0
Viewed 0 times
adapter patternstructural patterninterface compatibilitywrapperlegacy integrationthird party library

Problem

A third-party library or legacy module exposes an interface that is incompatible with what the rest of your code expects. You cannot modify either side.

Solution

Create an adapter class that wraps the incompatible component and exposes the expected interface. The adapter translates calls and data between the two shapes.

// What our app expects
interface Analytics {
  trackEvent(name: string, data: Record<string, unknown>): void;
}

// Third-party library with different API
class LegacyTracker {
  sendEvent(category: string, action: string, label: string) {
    console.log('Legacy:', category, action, label);
  }
}

// Adapter
class LegacyTrackerAdapter implements Analytics {
  constructor(private tracker: LegacyTracker) {}

  trackEvent(name: string, data: Record<string, unknown>): void {
    const label = JSON.stringify(data);
    this.tracker.sendEvent('app', name, label);
  }
}

// Usage: app only knows Analytics interface
const analytics: Analytics = new LegacyTrackerAdapter(new LegacyTracker());
analytics.trackEvent('page_view', { path: '/home' });

Why

The adapter isolates the incompatibility in one place. Switching to a different analytics provider means writing one new adapter, not changing every call site in the app.

Gotchas

  • Adapters can mask semantic differences — if sendEvent batches while trackEvent expects immediate dispatch, wrapping does not solve the semantic mismatch.
  • Object adapters (wrapping via composition) are preferred over class adapters (inheriting) in TypeScript because multiple inheritance is not supported.
  • Keep adapters thin. Business logic in an adapter is a maintenance burden.

Revisions (0)

No revisions yet.