Object-Oriented Programming in TypeScript: Encapsulation, Inheritance, and Polymorphism

Understanding Object-Oriented Programming

Object-oriented programming (OOP) is a programming paradigm that organizes software design around objects rather than actions. It focuses on classes, objects, inheritance, encapsulation, and polymorphism to create modular and reusable code structures.

Classes and Objects

In TypeScript, classes serve as blueprints for creating objects. A class defines properties (attributes) and methods (behaviors) that its instances will possess.

class Feline {
  speciesName: string;
  lifeStage: number;
  
  constructor(speciesName: string) {
    this.speciesName = speciesName;
    this.lifeStage = 3;
  }
  
  vocalize(): void {
    console.log(`Meow, I'm ${this.speciesName}`);
  }
}

const whiskers = new Feline("Whiskers");
console.log(whiskers); // Feline: { "speciesName": "Whiskers", "lifeStage": 3 }
whiskers.vocalize(); // "Meow, I'm Whiskers"

Inheritance

Inheritance allows classes to derive properties and methods from other classes, promoting code reuse and establishing hierarchical relationships.

class LivingCreature {
  speciesName: string;
  lifeStage: number;
  
  constructor(speciesName: string) {
    this.speciesName = speciesName;
    this.lifeStage = 3;
  }
  
  communicate() {
    console.log('...');
  }
}

class Feline extends LivingCreature {
  furColor: string;
  
  constructor(speciesName: string, furColor: string) {
    super(speciesName);
    this.furColor = furColor;
  }
}

Method Overriding

Subclasses can override parent class methods to provide specialized implementations.

class LivingCreature {
  speciesName: string;
  lifeStage: number;
  
  move() {
    console.log(`Parent class movement method!`);
  }
}

class Canine extends LivingCreature {
  bark() {
    console.log(`${this.speciesName} is barking!`);
  }
  
  move() {
    console.log(`Child class movement method overriding parent!`);
  }
}

Abstract Classes

Abstract classes cannot be instantiated directly and often contain abstract methods that must be implemented by subclasses.

abstract class LivingCreature {
  consume() {
    console.log('consuming');
  }
  abstract rest(): void;
}

class Canine extends LivingCreature {
  speciesName: string;
  
  constructor(speciesName: string) {
    super();
    this.speciesName = speciesName;
  }
  
  rest() {
    console.log('canine resting');
  }
}

Encapsulation

Encapsulation bundles data and methods together while controlling access through access modifiers.

Acces Modifiers

TypeScript provides three access modifiers: public (default), protected, and private.

class Person {
  private personalName: string;
  
  constructor(personalName: string) {
    this.personalName = personalName;
  }
  
  get name() {
    return this.personalName;
  }
  
  set name(personalName: string) {
    this.personalName = personalName;
  }
}

const individual = new Person('John');
console.log(individual.name); // Access via getter
individual.name = 'Jane';     // Modify via setter

Static Members

Static properties and methods belong to the class rather than instances.

class MathUtils {
  static PI = 3.1415926;
  
  static add(value1: number, value2: number) {
    return value1 + value2;
  }
}

console.log(MathUtils.PI);
console.log(MathUtils.add(10, 20));

Polymorphism

Polymorphism enables objects of different types to be treated as objects of a common super type.

abstract class LivingCreature {
  abstract rest(): void;
}

class Canine extends LivingCreature {
  rest() {
    console.log('canine resting');
  }
}

class Feline extends LivingCreature {
  rest() {
    console.log('feline resting');
  }
}

const dog = new Canine();
const cat = new Feline();

const creatures: LivingCreature[] = [dog, cat];

creatures.forEach(creature => {
  creature.rest(); // Different implementations based on actual type
});

Method Chaining with This Type

Methods can return 'this' to enable fluent interface patterns.

class ProcessFlow {
  initialStep() {
    return this;
  }
  
  subsequentStep() {
    return this;
  }
}

class CustomFlow extends ProcessFlow {
  customStep() {
    return this;
  }
}

new CustomFlow().customStep().initialStep().customStep().subsequentStep();

Tags: TypeScript OOP encapsulation Inheritance Polymorphism

Posted on Tue, 14 Jul 2026 16:07:15 +0000 by jarvis