How to Extend abstract class with Generics in Typescript ?
In Typescript, an abstract class is the base class that is inherited by other classes without having to define its members. Generic is the feature with which you can create a variable that represents a type in classes, functions, and type aliases that don't need to define the types that they use explicitly.
There are 3 approaches given below to extend an abstract class with generics:
Table of Content
Using a basic way to extend the abstract class with Generics
In this approach, we will see the basic way to extend the abstract class with generics with 3 steps:
- Create a class with an abstract keyword and add a generic type parameter using angle brackets (<>).
- Use the generic type parameters in methods or properties within the abstract class.
- Extend the abstract class from other classes by providing types for the generic parameters.
Syntax:
abstract class Classname<Generic> {
Visibility Prop_Name: Generic = Initial_Value;
Method_Name(Parameter: Generic): Return_Type{ ... }
}
class NormalClass extends Abstract_Class<Generic_Type> { ... }
Example : The below example will create a simple abstract class SuperClass with a generic type parameter T. It has a method pushItem that accepts an item of type T and stores it in an array of type T[].
abstract class SuperClass<T> {
protected NumArray: T[] = [];
pushNumber(num: T): void {
this.NumArray.push(num);
}
abstract ShowNumbers(): void;
}
class SubClass extends SuperClass<number> {
showNumbers(): void {
console.log("Pushed Numbers are: ",
this.NumArray.join(", "));
}
}
const numberSeries = new SubClass();
numberSeries.pushNumber(1);
numberSeries.pushNumber(2);
numberSeries.showNumbers();
Output:
Pushed Numbers are: 1, 2
Extending with Generic Constraints
Extending with the use of Generic Constraints can be done in the following 4 steps:
- Create an interface of generic type with constraints
- Create an abstract class with a generic type parameter constrained by the above interface
- Extend the abstract class with a class that implements the interface
- Extend the abstract class with the normal class by which the normal class will have the power to pass a class as a type
Syntax:
interface Interface_Name{ ... }
abstract class AbstractClass<T extends Interface_Name> { ... }
class ClassNameOne implements Interface_Name{ ... }
class ClassNameTwo extends AbstractClass<ClassNameOne > { ... }
Example: The below example creates a class that extends an abstract class with passing another class as a generic and the generic also extends some interface.
interface MethodGateway {
printName(): string;
}
abstract class AbstractClass<T extends MethodGateway> {
abstract printName(): T;
}
class ClassMethodExtender implements MethodGateway {
printName(): string {
return "GeeksforGeeks";
}
}
class NormalClass extends AbstractClass<ClassMethodExtender> {
printName(): ClassMethodExtender {
return new ClassMethodExtender();
}
}
const instance = new NormalClass();
console.log(instance.printName().printName());
Output:
GeeksforGeeks
With multiple type parameters in Generics
Passing multiple Type parameters is explained in 2 steps below:
- Create an abstract class with multiple generic type parameters like T,U...
- Extend the abstract class with specific types
Syntax:
abstract class AbstractClass<T, U, ...> { ... }
class NormalClass extends AbstractClass<DataType_1, DataType_2, ...> { ... }
Example: The below example uses string type to pass to generic types that allows the abstract class to assign type to two abstract properties key and value.
abstract class KeyValue<Key, Value> {
abstract key: Key;
abstract value: Value;
abstract display(): void;
}
class StringType extends KeyValue<string, string> {
key: string = "name";
value: string = "GeeksforGeeks";
display(): void {
console.log(`Key: ${this.key}, Value: ${this.value}`);
}
}
const instance = new StringType();
instance.display();
Output:
Key: name, Value: GeeksforGeeks