Diverse Examples of TypeScript Generics

Explore practical examples of TypeScript generics for enhanced code reusability.
By Jamie

Understanding TypeScript Generics

TypeScript generics are a powerful feature that allows developers to create reusable components that can work with various data types. By using generics, you can write functions, classes, and interfaces that are type-safe while maintaining flexibility. This results in cleaner, more maintainable code.

Example 1: Generic Function for Array Manipulation

Context

In many applications, you may need to manipulate arrays of different types. This example demonstrates a generic function that can sort any array of comparable items.

function sortArray<T>(arr: T[]): T[] {
    return arr.sort();
}

const numberArray = [5, 3, 8, 1, 2];
const stringArray = ['banana', 'apple', 'cherry'];

const sortedNumbers = sortArray(numberArray);
const sortedStrings = sortArray(stringArray);

console.log(sortedNumbers); // Output: [1, 2, 3, 5, 8]
console.log(sortedStrings); // Output: ['apple', 'banana', 'cherry']

Notes

  • The generic type T allows the function to accept an array of any data type, as long as the items can be sorted.
  • You may enhance this function by adding custom sorting logic based on specific criteria.

Example 2: Generic Interface for API Response

Context

When dealing with API responses, you often want to create a structure that can handle different types of data. This example illustrates a generic interface for API responses.

interface ApiResponse<T> {
    data: T;
    status: string;
    message: string;
}

function handleApiResponse<T>(response: ApiResponse<T>) {
    console.log(`Status: ${response.status}`);
    console.log(`Message: ${response.message}`);
    console.log('Data:', response.data);
}

const userResponse: ApiResponse<{ name: string; age: number }> = {
    data: { name: 'John Doe', age: 30 },
    status: 'success',
    message: 'User retrieved successfully',
};

handleApiResponse(userResponse);

Notes

  • The ApiResponse<T> interface can be used for any type of data, such as user information, product details, etc.
  • This enhances type safety and clarity when handling responses from different API endpoints.

Example 3: Generic Class for Stack Data Structure

Context

In data structures, a stack is a common implementation. This example demonstrates how to create a generic stack class that can store items of any type.

class Stack<T> {
    private items: T[] = [];

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

    pop(): T | undefined {
        return this.items.pop();
    }

    peek(): T | undefined {
        return this.items[this.items.length - 1];
    }

    isEmpty(): boolean {
        return this.items.length === 0;
    }
}

const numberStack = new Stack<number>();
numberStack.push(1);
numberStack.push(2);
numberStack.push(3);
console.log(numberStack.pop()); // Output: 3
console.log(numberStack.peek()); // Output: 2
console.log(numberStack.isEmpty()); // Output: false

Notes

  • This Stack<T> class can handle any type of data, providing flexibility in its usage.
  • You may extend the functionality by adding methods like clear() or size() to enhance its capabilities.