DEV Community

Cover image for Parametric Polymorphism in TypeScript and how it can help you to write better code
Shadid Haque
Shadid Haque

Posted on • Originally published at Medium

Parametric Polymorphism in TypeScript and how it can help you to write better code

Parametric Polymorphism

Polymorphism is a widely used concept in Object Oriented Programming. However, did you know there is more than one type of Polymorphism? In functional programming, there is this concept called Parametric Polymorphism. In JavaScript/TypeScript, this concept is used to write flexible, reusable, type-safe code.

function logArray<T>(arr: T[]): void {
  arr.forEach(element => console.log(element));
}

let numbers = [1, 2, 3];
logArray<number>(numbers); 
// 1
// 2
// 3

let words = ["hello", "world"];
logArray<string>(words);
// "hello"
// "world"

// union types [mixed]
let mixed = ["Some", "Mixed", 3, 5];
logArray<string | number>(mixed);
// "Some"
// "Mixed"
// 3
// 5
Enter fullscreen mode Exit fullscreen mode

In this example, the logArray function is a generic function that takes an array of elements of any type T, and logs each element to the console. The type of T is specified when calling the function, using the angle brackets syntax. You can also make a type T union of multiple types.

Let me give you another example to convey the usefulness of this. Take the following code snippet, for instance. The following code ensures improved type safety in your application.

function add<T>(a: T, b: T): T {
  return a + b;
}

let sum = add<number>(2, 3);
console.log(sum); // 5

// Compile-time error: 
// Argument of type '"hello"' is not assignable to parameter of type 'number'.
sum = add<number>("hello", 3);
Enter fullscreen mode Exit fullscreen mode

This forces you to catch errors in compile time and ensures predictability in your code.

Let’s take a look at a more practical application of this. Let’s say we have different types of products in an e-commerce application. Some products have discounts property; some products have international shipping etc. Now assume we want to display a slightly different view based on the product type. We can do this by creating a generic render function. The function can take in a diverse array of products, and based on type, it will render the appropriate view.The following code snippet demonstrates this.

type Product {
  name: string;
  price: number;
}

type DiscountedProduct = {
  name: string;
  price: number;
  discountAmout: number;
}

type InternationalShippingProduct = {
  name: string;
  price: number;
  limitedEdition: boolean;
}

function renderProducts<T>(arr: T[]): void {
  arr.forEach(item => {
   if(typeof item === 'object') {
     if(item.hasOwnProperty("discountAmout")) {
       // Render Product with Discount Amount
        console.log(`Discounted Product ${item.name}`)
      } else if (item.hasOwnProperty("limitedEdition")) {
       // Render International Shipping Product
        console.log(`International Shipping Product ${item.name}`)
      } else {
       // Render Normal Product
        console.log(`Product ${item.name}`)
      }
    }
  })
}

const productA: Product = {
 name: "T Shirt",
 price: 23.00
}

const productB: DiscountedProduct = {
 name: "Nike Shoe",
 price: 100.00,
 discountAmout: 10
}

const productC: InternationalShippingProduct = {
 name: "Designer Bag of some kind",
 price: 200.00,
 limitedEdition: true
}

const products = [productA, productB, productC]

renderProducts(products)interface Product {
  name: string;
  price: number;
}

type DiscountedProduct = {
  name: string;
  price: number;
  discountAmout: number;
}

type InternationalShippingProduct = {
  name: string;
  price: number;
  limitedEdition: boolean;
}

function renderProducts<T>(arr: T[]): void {
  arr.forEach(item => {
   if(typeof item === 'object') {
     if(item.hasOwnProperty("discountAmout")) {
       // Render Product with Discount Amount
        console.log(`Discounted Product ${item.name}`)
      } else if (item.hasOwnProperty("limitedEdition")) {
       // Render International Shipping Product
        console.log(`International Shipping Product ${item.name}`)
      } else {
       // Render Normal Product
        console.log(`Product ${item.name}`)
      }
    }
  })
}

const productA: Product = {
 name: "T Shirt",
 price: 23.00
}

const productB: DiscountedProduct = {
 name: "Nike Shoe",
 price: 100.00,
 discountAmout: 10
}

const productC: InternationalShippingProduct = {
 name: "Designer Bag of some kind",
 price: 200.00,
 limitedEdition: true
}

const products = [productA, productB, productC]

renderProducts(products)
Enter fullscreen mode Exit fullscreen mode

In computer science, Parametric polymorphism is essential because it allows functions and data types to be written generically so that they can handle values uniformly regardless of their data type. Parametric polymorphism can lead to more efficient code since it avoids the need for type-specific implementations. I hope this article gave you a basic understanding of what it is and how it can be used to write better code. That’s all for today. See you next time ✌️

Top comments (0)