Unleashing the Power of Generics in TypeScript: A Comprehensive Guide

Unleashing the Power of Generics in TypeScript: A Comprehensive Guide

ยท

3 min read

Introduction

  • Imagine a world where you could create functions, interfaces, and classes that work seamlessly with any data type, providing both flexibility and type safety.

  • Welcome to the world of Generics in TypeScript!

  • In this blog, we'll delve into the magic of Generics, exploring how they can make your TypeScript code more robust, reusable, and easier to maintain.

What are Generics?

  • Generics allow you to create components that can work with any data type while preserving type safety.

  • They are like placeholders for types, enabling you to write more flexible and reusable code.

  • Let's start with a simple example to see how Generics work.

  • Consider a function that returns the first element of an array. Without Generics, we might write it like this:

      function getFirstElement(arr: any[]): any {
        return arr[0];
      }
    

    While this works, it loses the type information of the array elements. By using Generics, we can retain the type information:

      function getFirstElement<T>(arr: T[]): T {
        return arr[0];
      }
    
      const numberArray = [1, 2, 3];
      const stringArray = ["a", "b", "c"];
    
      console.log(getFirstElement(numberArray)); // Output: 1
      console.log(getFirstElement(stringArray)); // Output: "a"
    

    Here, T is a type variable that acts as a placeholder for the type that will be provided when the function is called.

Real Life Example

Imagine you're building an e-commerce platform. You need a function to fetch product details, and these products can be of various types such as electronics, clothing, or groceries. Using Generics, you can create a flexible function that handles any product type.

interface Product {
  id: number;
  name: string;
  price: number;
}

interface Electronics extends Product {
  warranty: string;
}

interface Clothing extends Product {
  size: string;
}

function getProductDetails<T extends Product>(product: T): string {
  return `Product: ${product.name}, Price: $${product.price}`;
}

const laptop: Electronics = { id: 1, name: "Laptop", price: 1000, warranty: "1 year" };
const shirt: Clothing = { id: 2, name: "Shirt", price: 20, size: "M" };

console.log(getProductDetails(laptop)); // Output: Product: Laptop, Price: $1000
console.log(getProductDetails(shirt));  // Output: Product: Shirt, Price: $20

In this example, getProductDetails is a generic function that can handle any type extending the Product interface.

Advance Usage of Generics

Generics can also be used with interfaces and classes. Let's explore an example where we create a generic interface and a class that implements it.

interface Repository<T> {
  add(item: T): void;
  getById(id: number): T;
}

class InMemoryRepository<T> implements Repository<T> {
  private items: T[] = [];

  add(item: T): void {
    this.items.push(item);
  }

  getById(id: number): T {
    return this.items.find(item => (item as any).id === id);
  }
}

const productRepository = new InMemoryRepository<Product>();

productRepository.add(laptop);
productRepository.add(shirt);

console.log(productRepository.getById(1)); // Output: { id: 1, name: 'Laptop', price: 1000, warranty: '1 year' }

In this example, InMemoryRepository is a generic class that can handle any type that conforms to the Repository interface.

Conclusion

  • Generics in TypeScript are a powerful tool that can significantly enhance the flexibility and reusability of your code.

  • By using Generics, you can create functions, interfaces, and classes that work with any data type while maintaining type safety.

  • Whether you're building a small utility function or a complex data repository, Generics can help you write cleaner and more maintainable code.

Thank You Everyone For The Read ....

Happy Coding! ๐Ÿคž๐Ÿ’ป


๐Ÿ‘‹ Hello, I'm Aaryan Bajaj .

๐Ÿฅฐ If you liked this article, consider sharing it.

๐Ÿ”— X | LinkedIn

ย