Polymorphism in C#, JavaScript, and TypeScript
Master polymorphism patterns across languages.
By EMEPublished: February 20, 2025
polymorphismoopinheritanceinterfaces
A Simple Analogy
Polymorphism is like a universal remote. One button works on different devices with different behaviors.
Why Polymorphism?
- Flexibility: Same interface, different implementations
- Extensibility: Add new types without changes
- Maintenance: Code to interfaces, not implementations
- Testing: Mock different implementations
- Clarity: Express intent through types
C# Polymorphism
// Interface
public interface IShape
{
double GetArea();
}
// Implementations
public class Circle : IShape
{
public double Radius { get; set; }
public double GetArea() => Math.PI * Radius * Radius;
}
public class Rectangle : IShape
{
public double Width { get; set; }
public double Height { get; set; }
public double GetArea() => Width * Height;
}
// Usage
IShape shape = new Circle { Radius = 5 };
double area = shape.GetArea();
TypeScript Polymorphism
interface Animal {
name: string;
makeSound(): string;
}
class Dog implements Animal {
name: string;
makeSound(): string {
return "Woof";
}
}
class Cat implements Animal {
name: string;
makeSound(): string {
return "Meow";
}
}
function animalSound(animal: Animal) {
console.log(animal.makeSound());
}
JavaScript Duck Typing
// No interface - just the shape matters
const dog = {
name: "Buddy",
makeSound: () => "Woof"
};
const cat = {
name: "Whiskers",
makeSound: () => "Meow"
};
function playSound(animal) {
console.log(animal.makeSound());
}
playSound(dog); // Woof
playSound(cat); // Meow
Best Practices
- Program to interfaces: Not concrete types
- Dependency injection: Accept interfaces
- Single responsibility: One reason to change
- Liskov substitution: Subtypes are substitutable
- Clarity: Make polymorphism obvious
Related Concepts
- Inheritance
- Interfaces
- Abstract classes
- Design patterns
Summary
Polymorphism enables code reuse through common interfaces. C# uses explicit types, JavaScript uses duck typing.