SOLID Pattern — Liskov Substitution Principle
kbartsch

kbartsch @mor3

Joined:
May 6, 2025

SOLID Pattern — Liskov Substitution Principle

Publish Date: May 6
0 0

SOLID Pattern — Liskov Substitution Principle

Welcome back to the last article on my SOLID pattern research by myself. As software engineers, we strive to write code that is not only functional but also maintainable, scalable, and robust. In object-oriented programming, adhering to solid principles is crucial for achieving these goals. One such principle is the Liskov Substitution Principle (LSP), named after Barbara Liskov, which states that objects of a superclass should be replaceable with objects of its subclasses without affecting the correctness of the program.

Level: None

In TypeScript, a superset of JavaScript, we can leverage the static type system to enforce the Liskov Substitution Principle effectively. Let’s delve into some code examples to understand how this principle works and its implications.

Consider the classic example of shapes, where we have a superclass Shape and subclasses Circle and Square. According to LSP, we should be able to substitute Circle and Square objects wherever Shape objects are expected.

class Shape {
    area(): number {
        throw new Error("Method not implemented.");
    }
}

class Circle extends Shape {
    radius: number;

    constructor(radius: number) {
        super();
        this.radius = radius;
    }

    area(): number {
        return Math.PI * this.radius * this.radius;
    }
}

class Square extends Shape {
    sideLength: number;

    constructor(sideLength: number) {
        super();
        this.sideLength = sideLength;
    }

    area(): number {
        return this.sideLength * this.sideLength;
    }
}
Enter fullscreen mode Exit fullscreen mode

Now, let’s say we have a function calculateArea that expects an array of shapes and computes the total area:

function calculateArea(shapes: Shape[]): number {
    let totalArea = 0;
    shapes.forEach(shape => {
        totalArea += shape.area();
    });
    return totalArea;
}
Enter fullscreen mode Exit fullscreen mode

By following LSP, we can confidently pass an array of Circle and Square objects to calculateArea, knowing that it will work as expected:

const shapes: Shape[] = [new Circle(5), new Square(4)];
console.log(calculateArea(shapes)); // Output: 103.67 (approximately)
Enter fullscreen mode Exit fullscreen mode

One advantage of adhering to LSP is the flexibility it provides. We can easily extend our system by adding new subclasses without modifying existing code. However, violating LSP can lead to unexpected behavior and bugs. For example, if we introduce a Triangle class that doesn't override the area method properly, it can break the behavior of calculateArea.

class Triangle extends Shape {
    base: number;
    height: number;

    constructor(base: number, height: number) {
        super();
        this.base = base;
        this.height = height;
    }
}

const shapes: Shape[] = [new Circle(5), new Square(4), new Triangle(3, 6)];
console.log(calculateArea(shapes)); // Output: NaN (Not a Number)
Enter fullscreen mode Exit fullscreen mode

Conclusion: Liskov Substitution Principle plays a crucial role in designing robust and maintainable software systems. By adhering to this principle in TypeScript, we can write code that is not only type-safe but also flexible and easily extensible. Remember, honoring LSP leads to cleaner, more reliable code that stands the test of time.

Hope the article was helpful. For the next and last story on this topic a summarized version of all patterns will be writen shortly. If you like what I do feel free to share and follow me! Have a great day!


Photo by Christina @ wocintechchat.com on Unsplash

Comments 0 total

    Add comment