How to Develop Generic Classes



Before developing the actual generic class, let's first learn about the Generic class. A TypeScript class known as generic may deal with numerous types of data. It is a variety of arguments and is displayed using angle brackets (<>). This represents the kind of data the class will use to achieve this. The type argument can then be used in the class's properties and functions to make the class flexible and reusable with other data types.

We will be briefing a little bit. Suppose, in an example, the type parameter is denoted as "T" and the property "value" of the simple generic class "MyGenericClass". "T" and "value" can both be created. The "value" property will then have the appropriate type if this class is instantiated with alternative kinds, such as "number" or "string."

Since the same class may be used with several data types, this gives your code additional flexibility and reuse. You can also use constraints to restrict the kinds used as type parameters.

Syntax

The syntax for creating a generic class in TypeScript is as follows -

class ClassName<TypeParameter> {
   // class properties and methods
}

Where "ClassName" is the name of the class, and "TypeParameter" is the placeholder for the type of data the class will work with.

Example 1

This example demonstrates using a generic class in TypeScript to create a class that can work with multiple data types. The class is defined with a type parameter T which is used in the properties and methods of the class, allowing the class to be flexible and reusable with different types of data. The class "Queue" has a private property called "data, " an array of type T.

The class also has three methods: "enqueue", which adds an item to the end of the queue, "dequeue", which removes an item from the front of the queue and "peek", which returns the item at the front of the queue without removing it. We have created two instances of the Queue class, one for numbers and the other for strings. The class can work with different data types, making our code more flexible and reusable.

class Queue<T> {
   private data: T[] = []

   // add an item to the end of the queue
   enqueue(item: T) {
      this.data.push(item)
   }

   // remove an item from the front of the queue
   dequeue(): T | undefined {
      return this.data.shift()
   }

   // get the item at the front of the queue
   peek(): T | undefined {
      return this.data[0]
   }
}
let numberQueue = new Queue<number>()
numberQueue.enqueue(1)
numberQueue.enqueue(2)
console.log(numberQueue.peek())
console.log(numberQueue.dequeue())
console.log(numberQueue.peek())

let stringQueue = new Queue<string>()
stringQueue.enqueue('Hello')
stringQueue.enqueue('world')
console.log(stringQueue.peek())
console.log(stringQueue.dequeue())
console.log(stringQueue.peek())

On compiling, it will generate the following JavaScript code.

var Queue = /** @class */ (function () {
   function Queue() {
      this.data = [];
   }
   // add an item to the end of the queue
   Queue.prototype.enqueue = function (item) {
      this.data.push(item);
   };
   // remove an item from the front of the queue
   Queue.prototype.dequeue = function () {
      return this.data.shift();
   };
   // get the item at the front of the queue
   Queue.prototype.peek = function () {
      return this.data[0];
   };
   return Queue;
}());
var numberQueue = new Queue();
numberQueue.enqueue(1);
numberQueue.enqueue(2);
console.log(numberQueue.peek());
console.log(numberQueue.dequeue());
console.log(numberQueue.peek());
var stringQueue = new Queue();
stringQueue.enqueue('Hello');
stringQueue.enqueue('world');
console.log(stringQueue.peek());
console.log(stringQueue.dequeue());
console.log(stringQueue.peek());

Output 

The above code will produce the following output –

1
1
2
Hello
Hello
world

Example 2

In this example, we will develop another generic class with two generic types of properties. The "KeyValuePair" class has two private properties, "key" and "value", of type T and U, respectively. The class also has two methods, "getKey" and "getValue", that return the key and value properties, respectively.

The class can be instantiated with data types, such as numbers, strings, or objects, for both key and value. We have created two instances of the KeyValuePair class, one with string as key and number as value, and the other with string as key and object as a value. The class can work with different data types for both key and value, making our code more flexible and reusable.

class KeyValuePair<T, U> {
   private key: T
   private value: U

   constructor(key: T, value: U) {
      this.key = key
      this.value = value
   }

   // method to get the key
   getKey(): T {
      return this.key
   }

   // method to get the value
   getValue(): U {
      return this.value
   }
}

let numberKeyValuePair = new KeyValuePair<string, number>('age', 20)
console.log(numberKeyValuePair.getKey()) // "age"
console.log(numberKeyValuePair.getValue()) // 20

let objectKeyValuePair = new KeyValuePair<string, object>('person', {
   name: 'Tutorialspoint',
   age: 10,
})
console.log(objectKeyValuePair.getKey()) // "person"
console.log(objectKeyValuePair.getValue()) // {name: "Tutorialspoint", age: 10}

On compiling, it will generate the following JavaScript code.

var KeyValuePair = /** @class */ (function () {
   function KeyValuePair(key, value) {
      this.key = key;
      this.value = value;
   }
   // method to get the key
   KeyValuePair.prototype.getKey = function () {
      return this.key;
   };
   // method to get the value
   KeyValuePair.prototype.getValue = function () {
      return this.value;
   };
   return KeyValuePair;
}());
var numberKeyValuePair = new KeyValuePair('age', 20);
console.log(numberKeyValuePair.getKey()); // "age"
console.log(numberKeyValuePair.getValue()); // 20
var objectKeyValuePair = new KeyValuePair('person', {
   name: 'Tutorialspoint',
   age: 10
});
console.log(objectKeyValuePair.getKey()); // "person"
console.log(objectKeyValuePair.getValue()); // {name: "Tutorialspoint", age: 10}

Output 

The above code will produce the following output –

age
20
person
{ name: 'Tutorialspoint', age: 10 }

Using generic classes in TypeScript can lead to more flexible, reusable, and maintainable code. Additionally, TypeScript's type-checking system ensures that the types used in a generic class are used correctly at compile-time, further improving the code's overall quality and safety. Generic classes are a powerful feature of TypeScript that can be used to write more reliable and reusable codes.


Advertisements