Duck Typing in TypeScript

Duck typing is a programming concept where an object's type is determined by its behavior (methods and properties) rather than its class inheritance. The name comes from the phrase "If it walks like a duck and quacks like a duck, then it must be a duck."

What is Duck Typing?

Duck typing focuses on what an object can do rather than what it is. If two objects have the same methods and properties, they can be used interchangeably, regardless of their actual class or type.

Duck Typing in TypeScript

TypeScript implements duck typing through interfaces. An interface defines the structure an object must have - specifying required methods and properties without caring about the object's actual class.

For example, if an interface requires a method called fly(), any object with that method can be treated as that type, enabling greater code flexibility and reusability.

Basic Example

Here's a simple demonstration of duck typing with TypeScript interfaces:

interface Duck {
   quack(): void;
}

class MallardDuck implements Duck {
   quack(): void {
      console.log("Quack!");
   }
}

class RubberDuck implements Duck {
   quack(): void {
      console.log("Squeak!");
   }
}

// Both can be used as Duck type
let duck1: Duck = new MallardDuck();
let duck2: Duck = new RubberDuck();

duck1.quack(); // Output: "Quack!"
duck2.quack(); // Output: "Squeak!"

Practical Example: Flyable Objects

This example shows how different objects can share the same interface behavior:

interface Flyable {
   fly(): void;
}

class Bird implements Flyable {
   fly(): void {
      console.log("Bird is flying");
   }
}

class Plane implements Flyable {
   fly(): void {
      console.log("Plane is flying");
   }
}

function goFly(flyable: Flyable) {
   flyable.fly();
}

let bird = new Bird();
let plane = new Plane();

goFly(bird); // Prints "Bird is flying"
goFly(plane); // Prints "Plane is flying"

On compiling, it will generate the following JavaScript code:

var Bird = /** @class */ (function () {
   function Bird() {
   }
   Bird.prototype.fly = function () {
      console.log("Bird is flying");
   };
   return Bird;
}());

var Plane = /** @class */ (function () {
   function Plane() {
   }
   Plane.prototype.fly = function () {
      console.log("Plane is flying");
   };
   return Plane;
}());

function goFly(flyable) {
   flyable.fly();
}

var bird = new Bird();
var plane = new Plane();

goFly(bird);
goFly(plane);
Bird is flying
Plane is flying

Another Example: Driveable Interface

Here's another example demonstrating duck typing with vehicles:

interface Driveable {
  drive(): void;
}

class Car implements Driveable {
  drive(): void {
    console.log("Car is driving");
  }
}

class Truck implements Driveable {
  drive(): void {
    console.log("Truck is driving");
  }
}

function goDrive(driveable: Driveable) {
  driveable.drive();
}

let car = new Car();
let truck = new Truck();

goDrive(car);
goDrive(truck);
Car is driving
Truck is driving

Benefits of Duck Typing

Duck typing provides several key advantages:

  • Flexibility: Code works with any object that has the required methods, not just specific types
  • Reusability: Functions can operate on different object types without modification
  • Loose Coupling: Code depends on behavior rather than concrete implementations
  • Polymorphism: Objects of different types can be used interchangeably

Key Points

  • TypeScript interfaces enable duck typing through structural typing
  • Objects are compatible if they have the same structure, regardless of class
  • Duck typing promotes writing flexible, reusable code
  • The typeof keyword can be used for runtime type checking when needed

Conclusion

Duck typing in TypeScript allows objects to be used interchangeably based on their behavior rather than their type. This approach leads to more flexible and maintainable code by focusing on what objects can do rather than what they are.

Updated on: 2026-03-15T23:19:00+05:30

1K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements