Liskov Substitution
The L in SOLID: if B extends A, you should be able to use B anywhere you use A without breaking things. A subclass shouldn't remove or break behavior its parent promises.
// Bad: Penguin breaks what Bird promises
class Bird {
fly() { return "flying" }
}
class Penguin extends Bird {
fly() { throw new Error("Can't fly!") } // surprise!
}
// Good: only birds that can fly promise fly()
class Bird {
eat() { return "eating" }
}
class FlyingBird extends Bird {
fly() { return "flying" }
}
class Sparrow extends FlyingBird {}
class Penguin extends Bird {}