---
title: Liskov Substitution
description: Subtypes must be substitutable for their base types without altering program correctness.
tokens: ~295
---

# Liskov Substitution

Subclasses must work wherever the base class works. If your code uses a parent class, it should be able to use any subclass without knowing which one it is. A subclass can add new behavior, but it cannot remove or break behavior the parent promised.

Two red flags that you are violating LSP:
- A subclass throws an exception for a method the parent provides
- Callers need `instanceof` checks to handle specific subclasses

## Example

`Penguin` extends `Bird` but breaks the expectation that all birds can fly:

```typescript
class Bird {
  fly(): void {
    // flying logic
  }
}

class Penguin extends Bird {
  fly(): void {
    throw new Error("Penguins can't fly");
  }
}
```

Split the flying behavior into its own interface so only birds that can actually fly implement it:

```typescript
abstract class Bird {
  abstract eat(): void;
}

abstract class FlyingBird extends Bird {
  abstract fly(): void;
}

class Sparrow extends FlyingBird {
  eat(): void {}
  fly(): void {}
}

class Penguin extends Bird {
  eat(): void {}
}
```

Now any code that works with `Bird` can accept a `Penguin` without breaking. Code that specifically needs a flying bird uses `FlyingBird`.