Defining a generic class is a powerful feature in programming that allows developers to create classes that can operate on different data types while maintaining type safety. This concept is particularly prevalent in languages like Java, C#, and TypeScript. By using generics, you can write more flexible and reusable code without sacrificing the benefits of strong typing.
In a generic class, you define one or more type parameters that act as placeholders for the actual data types that will be used when an instance of the class is created. This approach allows the same class to work with various data types without needing to overload methods or create multiple versions of the class.
In TypeScript, you can define a generic class using angle brackets to specify the type parameters. Here’s a simple example of a generic class that represents a container for any type of data:
class Container<T> {
private items: T[] = [];
add(item: T): void {
this.items.push(item);
}
get(index: number): T {
return this.items[index];
}
getAll(): T[] {
return this.items;
}
}
To use the generic class, you can specify the type when creating an instance:
const numberContainer = new Container<number>();
numberContainer.add(1);
numberContainer.add(2);
console.log(numberContainer.getAll()); // Output: [1, 2]
const stringContainer = new Container<string>();
stringContainer.add("Hello");
stringContainer.add("World");
console.log(stringContainer.getAll()); // Output: ["Hello", "World"]
interface Comparable {
compareTo(other: this): number;
}
class SortedContainer<T extends Comparable> {
private items: T[] = [];
add(item: T): void {
this.items.push(item);
this.items.sort((a, b) => a.compareTo(b));
}
}
In conclusion, defining a generic class enhances code reusability and type safety. By following best practices and avoiding common pitfalls, developers can create robust and flexible applications that can handle various data types effectively.