Learn how to make incompatible APIs work together seamlessly with the Adapter Pattern, a practical fix for real-world integration headaches.

Introduction
You’ve probably faced this:
- You integrate with a third-party API, only to find the response shape doesn’t match your app’s expectations.
- You swap a library (say, Axios → Fetch), and suddenly your function signatures don’t line up.
- You’re forced to write messy glue code everywhere just to make things work.
This is the exact pain the Adapter Pattern was made for.
Instead of littering your codebase with workarounds, you create a single, consistent interface and an “adapter” that makes the external API play nicely with your code.
In this article, we’ll cover:
- ✅ What the Adapter Pattern is and why it matters
- ✅ Real-world examples (Axios, Stripe, legacy APIs)
- ✅ Step-by-step implementation in JavaScript/TypeScript
- ✅ When to use it (and when not to)
- ✅ Gotchas & pro tips from real projects
By the end, you’ll see how this pattern helps you write cleaner, more maintainable integration code that doesn’t fall apart when APIs change.
What is the Adapter Pattern?
The Adapter Pattern is a structural design pattern that allows incompatible interfaces to work together by providing a wrapper (adapter) that translates one interface into another.
👉 Analogy: Think of a power plug adapter. Your laptop charger has a U.S. plug, but you’re in Europe. Instead of replacing your charger or rewiring your laptop, you use a plug adapter. Same electricity, different interface.
Why Developers Need It
You’ll need an adapter when:
- Third-party APIs return data in a different shape than your app needs.
- You’re migrating libraries, but don’t want to refactor your entire codebase.
- You need to support multiple providers (e.g., Stripe + PayPal + Square).
- You’re working with legacy code that you can’t change directly.
Without an adapter, you’re stuck with workarounds, duplicate code, and brittle integrations.
Real-World Example: Payment Gateways
Imagine you’re building a payment system. Your app expects every provider to expose a pay(amount: number)
function.
But Stripe, PayPal, and Square all have different APIs.
Without an Adapter (messy code)
function processPayment(method: string, amount: number) {
if (method === "stripe") {
stripe.charge(amount, "usd");
} else if (method === "paypal") {
paypal.makePayment({ amount });
} else if (method === "square") {
square.process({ total: amount, currency: "USD" });
}
}
Each time you add a new provider, you pile on another if
.
The Adapter Pattern in Action
Step 1: Define a Common Interface
interface PaymentProvider {
pay(amount: number): void;
}
Step 2: Create Adapters
class StripeAdapter implements PaymentProvider {
constructor(private stripe: any) {}
pay(amount: number) {
this.stripe.charge(amount, "usd");
}
}
class PayPalAdapter implements PaymentProvider {
constructor(private paypal: any) {}
pay(amount: number) {
this.paypal.makePayment({ amount });
}
}
class SquareAdapter implements PaymentProvider {
constructor(private square: any) {}
pay(amount: number) {
this.square.process({ total: amount, currency: "USD" });
}
}
Step 3: Use Adapters Through a Unified API
class StripeAdapter implements PaymentProvider {
constructor(private stripe: any) {}
pay(amount: number) {
this.stripe.charge(amount, "usd");
}
}
class PayPalAdapter implements PaymentProvider {
constructor(private paypal: any) {}
pay(amount: number) {
this.paypal.makePayment({ amount });
}
}
class SquareAdapter implements PaymentProvider {
constructor(private square: any) {}
pay(amount: number) {
this.square.process({ total: amount, currency: "USD" });
}
}
Now your app talks to a consistent API, no matter the provider.
Another Example: Fetch vs Axios
Let’s say you switch from Axios to Fetch, but your codebase expects the same interface.
Adapter Example
interface HttpClient {
get(url: string): Promise<any>;
}
class AxiosAdapter implements HttpClient {
constructor(private axios: any) {}
async get(url: string) {
const response = await this.axios.get(url);
return response.data;
}
}
class FetchAdapter implements HttpClient {
async get(url: string) {
const response = await fetch(url);
return response.json();
}
}
// Usage
let client: HttpClient = new AxiosAdapter(axios);
client.get("/users"); // works with Axios
client = new FetchAdapter();
client.get("/users"); // works with Fetch
You can switch libraries without rewriting your entire app.
Benefits of the Adapter Pattern
- Consistency: Your app interacts with a uniform API.
- Maintainability: Replace third-party libs without massive rewrites.
- Reusability: Use adapters across multiple projects.
- Future-proofing: Add new providers without touching core logic.
Gotchas & Things to Watch For
- Overengineering risk: If you’ll only ever use one provider, an adapter is unnecessary.
- Hidden complexity: Adapters can hide breaking changes; test carefully when providers update.
- Performance trade-offs: Adding wrappers can introduce minor overhead (usually negligible).
Pro Tip: Combine Adapter with Factory
Often, you’ll want to dynamically choose adapters based on configuration.
class PaymentFactory {
static create(provider: string): PaymentProvider {
switch (provider) {
case "stripe":
return new StripeAdapter(stripe);
case "paypal":
return new PayPalAdapter(paypal);
default:
throw new Error("Unsupported provider");
}
}
}
// Usage
const paymentProvider = PaymentFactory.create("paypal");
paymentProvider.pay(300);
This makes swapping providers as simple as changing a config.
Conclusion
The Adapter Pattern isn’t just theory, it’s a practical solution for one of the most annoying real-world problems: API mismatches.
Instead of littering your code with conditionals and provider-specific hacks, you build a bridge that lets your app stay clean, consistent, and flexible.
✅ Key takeaway: Stop rewriting your code for every API. Wrap it. Adapt it. Move on.
Call to Action
Have you ever fought with mismatched APIs or library migrations? How did you solve it? Share your story in the comments 👇
And if you know a teammate struggling with messy integration code, send them this article. They’ll thank you later.
Leave a Reply