Understanding Generic Classes in TypeScript: Flexible and Efficient Data Management
Tags: typescript, javascript
Published: 2024-06-11 15:04:35

In today's blog, we're diving into the fascinating world of generic classes in TypeScript. Generics allow us to create reusable, flexible, and efficient code that can handle various data types. Whether you're working with numbers, strings, or custom objects, generics make your life a whole lot easier. 🌟

{% embed https://www.youtube.com/watch?v=1WQel24c_wE %}

Let's break it down step by step.


### What Are Generic Classes? 🤔

Just like interfaces and functions, classes in TypeScript can also be generic. This means you can define a class to handle different types of data without specifying the exact data type upfront. Imagine you have a class designed to manage a collection of data. Initially, you might define it to handle strings, but what if you later need it to handle numbers or custom objects? That's where generics come in handy.

### Setting Up a Generic Class 🛠️

Here's a basic example to illustrate the concept. We'll create a generic class called `DataCollection` that can manage various data types.

`class DataCollection<T> {
    data: T[]
    constructor(data: T[]) {
        this.data = data;
    }

    loadOne(): T {
        const index = Math.floor(Math.random() * this.data.length);
        return this.data[index];
    }

    loadAll(): T[] {
        return this.data;
    }

    add(value: T): T[] {
        this.data.push(value);
        return this.data;
    }
}`

## Breaking Down the Code 🔍

- Generic Parameter <T>:
The <T> after the class name indicates that this class is generic. T represents the type that the class will handle.

- Constructor:
The constructor accepts an array of type T and assigns it to the data property.

- Methods:

- `loadOne()`: Returns a random item from the data array.
- `loadAll()`: Returns the entire data array.
- `add(value: T)`: Adds a new item of type T to the data array and returns the updated array.

## Using the Generic Class 📚

Let's see how to use this generic class with different data types.

## Example 1: Handling Strings 🍏🍌🍒

```const stringCollection = new DataCollection<string>(['apple', 'banana', 'cherry']);
console.log(stringCollection.loadOne()); // Random string
console.log(stringCollection.loadAll()); // ['apple', 'banana', 'cherry']
console.log(stringCollection.add('date')); // ['apple', 'banana', 'cherry', 'date']```


## Example 2: Handling Numbers 🔢

`const numberCollection = new DataCollection<number>([1, 2, 3]);
console.log(numberCollection.loadOne()); // Random number
console.log(numberCollection.loadAll()); // [1, 2, 3]
console.log(numberCollection.add(4)); // [1, 2, 3, 4]`

## Example 3: Handling Custom Objects 👥

`interface User {
    name: string;
    score: number;
}

const userCollection = new DataCollection<User>([
    { name: 'Mario', score: 100 },
    { name: 'Luigi', score: 80 },
]);

console.log(userCollection.loadOne()); // Random User
console.log(userCollection.loadAll()); // Array of Users
console.log(userCollection.add({ name: 'Peach', score: 90 })); // Updated Array`

## Why Use Generics? 🤓
- **Flexibility**: Handle multiple data types with a single class.

- **Reusability**: Write the class once and use it for different types of data.

- **Type Safety**: Ensure that the data type remains consistent throughout the class.

## Conclusion 🏁

Generic classes in TypeScript are a powerful feature that enhances code flexibility, reusability, and type safety. By using generics, you can create robust and efficient data management solutions that cater to various data types without duplicating code. So, next time you're working on a project that requires handling different types of data, give generics a try and experience the magic yourself! ✨