Exploring TypeScript Generics in Interfaces and Classes

by Nov 5, 2023typescript generics

In our journey through TypeScript generics, we’ve learned how to use them with functions. But generics don’t stop there; they extend their power to interfaces and classes, enabling us to create flexible and reusable data structures with impeccable type safety. In this chapter, we’ll explore how generics can be applied to interfaces and classes and showcase their real-world applications.

Applying Generics to Interfaces

Interfaces in TypeScript define the structure of an object, specifying the shape of its properties and their types. With generics, we can create interfaces that work with a variety of data types while maintaining type safety.

Let’s start with a simple example by creating a generic interface for key-value pairs:

interface KeyValuePair<K, V> {
  key: K;
  value: V;
}

const pair1: KeyValuePair<number, string> = { key: 1, value: "one" };
const pair2: KeyValuePair<string, boolean> = { key: "enabled", value: true };

In this example, KeyValuePair is a generic interface with two type parameters K and V. It can represent key-value pairs of different data types. The flexibility of this generic interface allows us to work with various combinations of key and value types.

Another practical example:

Suppose you want to create a generic interface to represent a collection of items with varying types. You can do so like this:

interface Collection<T> {
  items: T[];
  add(item: T): void;
  remove(item: T): void;
}

// Example usage
const numberCollection: Collection<number> = {
  items: [1, 2, 3],
  add(item) {
    this.items.push(item);
  },
  remove(item) {
    const index = this.items.indexOf(item);
    if (index !== -1) {
      this.items.splice(index, 1);
    }
  },
};

numberCollection.add(4);
numberCollection.remove(2);

The Collection interface is generic, with a type parameter T. It defines three members:

  • items: T[]: This member represents an array of items of type T. It’s used to store the collection’s elements.
  • add(item: T): void: This method takes an argument of type T and is responsible for adding an item to the collection.
  • remove(item: T): void: This method takes an argument of type T and is responsible for removing an item from the collection.
  • In this example, a numberCollection object is created. It’s of type Collection<number, which means it’s a collection of numbers.
  • The items property is initialized with an array [1, 2, 3]. This array stores the numbers in the collection.
  • The add method is defined as a function that takes an argument item, which is expected to be a number. It uses this.items.push(item) to add the specified number to the collection.
  • The remove method is defined as a function that takes an argument item, which is expected to be a number. It uses this.items.indexOf(item) to find the index of the specified number in the collection. If the number is found (index is not -1), it uses this.items.splice(index, 1) to remove the number from the collection.
  • The numberCollection object is now an instance of the Collection<number> interface, which means it must adhere to the interface’s structure and type constraints. It can be used to add and remove numbers from the collection.

Creating Generic Classes

Just like interfaces, classes in TypeScript can also benefit from generics. With generic classes, you can create reusable data structures and components. Let’s look at a practical example:

class Box<T> {
  private value: T;

  constructor(initialValue: T) {
    this.value = initialValue;
  }

  getValue(): T {
    return this.value;
  }

  setValue(newValue: T): void {
    this.value = newValue;
  }
}

Class Definition:

  • class Box<T>: This line defines a TypeScript class called Box. The <T> in the class definition indicates that Box is a generic class with a type parameter T. T is a placeholder for the data type that will be specified when creating instances of the class.

Class Members:

  • private value: T;: This line declares a private member variable value of type T. It’s where the class stores the value of the specified data type.

Constructor:

  • constructor(initialValue: T): This is the class constructor. It takes an initial value of type T as a parameter. When you create an instance of the Box class, you must provide an initial value of the specific data type.
    • this.value = initialValue;: Inside the constructor, the value member variable is initialized with the provided initialValue. The value’s data type is inferred from the type parameter T.

Methods:

  • getValue(): T: This method returns the stored value. It specifies that the return type is of the same type T as the stored value.
  • setValue(newValue: T): void: This method allows you to set a new value of type T. It takes the new value as a parameter.

Usage:

  • const numberBox = new Box<number>(42);: Here, we create an instance of the Box class for numbers. We specify <number> in the angle brackets to indicate that this instance will work with numbers. We provide an initial value of 42.
  • console.log(numberBox.getValue());: We call the getValue method to retrieve the stored value, which is 42.
  • const stringBox = new Box<string>("Hello, TypeScript");: Similarly, we create another instance of the Box class, this time for strings. We specify <string> and provide an initial value of "Hello, TypeScript".
  • console.log(stringBox.getValue());: We call the getValue method to retrieve the stored string value.

In this example, the generic class Box allows you to store and retrieve values of different data types while maintaining type safety. The type parameter T ensures that the stored value and the retrieved value are of the same data type.

Creating a multiplication Skill in Alexa using python

Written By Monisha Macharla

Hi, I'm Monisha. I am a tech blogger and a hobbyist. I am eager to learn and explore tech related stuff! also, I wanted to deliver you the same as much as the simpler way with more informative content. I generally appreciate learning by doing, rather than only learning. Thank you for reading my blog! Happy learning!

RELATED POSTS

Advanced Generics: Higher-Order Functions

Advanced Generics: Higher-Order Functions

In our journey through TypeScript generics, we've covered the basics, interfaces, and classes. Now, it's time to explore advanced concepts by combining generics with higher-order functions. These functions, which take other functions as arguments or return them,...

Basic Usage of Generics in Typescript

Basic Usage of Generics in Typescript

Keypoints Show how to declare generic functions and classes in TypeScript. Provide examples of generic functions that work with different data types. Demonstrate the use of built-in generics like Array<T> and Promise<T>. Here's the content...

VIDEOS – FOLLOW US ON YOUTUBE

EXPLORE OUR IOT PROJECTS

IoT Smart Gardening System – ESP8266, MQTT, Adafruit IO

Gardening is always a very calming pastime. However, our gardens' plants may not always receive the care they require due to our active lifestyles. What if we could remotely keep an eye on their health and provide them with the attention they require? In this article,...

How to Simulate IoT projects using Cisco Packet Tracer

In this tutorial, let's learn how to simulate the IoT project using the Cisco packet tracer. As an example, we shall build a simple Home Automation project to control and monitor devices. Introduction Firstly, let's quickly look at the overview of the software. Packet...

All you need to know about integrating NodeMCU with Ubidots over MQTT

In this tutorial, let's discuss Integrating NodeMCU and Ubidots IoT platform. As an illustration, we shall interface the DHT11 sensor to monitor temperature and Humidity. Additionally, an led bulb is controlled using the dashboard. Besides, the implementation will be...

All you need to know about integrating NodeMCU with Ubidots over Https

In this tutorial, let's discuss Integrating NodeMCU and Ubidots IoT platform. As an illustration, we shall interface the DHT11 sensor to monitor temperature and Humidity. Additionally, an led bulb is controlled using the dashboard. Besides, the implementation will be...

How to design a Wireless Blind Stick using nRF24L01 Module?

Introduction Let's learn to design a low-cost wireless blind stick using the nRF24L01 transceiver module. So the complete project is divided into the transmitter part and receiver part. Thus, the Transmitter part consists of an Arduino Nano microcontroller, ultrasonic...

Sending Temperature data to ThingSpeak Cloud and Visualize

In this article, we are going to learn “How to send temperature data to ThingSpeak Cloud?”. We can then visualize the temperature data uploaded to ThingSpeak Cloud anywhere in the world. But "What is ThingSpeak?” ThingSpeak is an open-source IoT platform that allows...

Amaze your friend with latest tricks of Raspberry Pi and Firebase

Introduction to our Raspberry Pi and Firebase trick Let me introduce you to the latest trick of Raspberry Pi and Firebase we'll be using to fool them. It begins with a small circuit to connect a temperature sensor and an Infrared sensor with Raspberry Pi. The circuit...

How to implement Machine Learning on IoT based Data?

Introduction The industrial scope for the convergence of the Internet of Things(IoT) and Machine learning(ML) is wide and informative. IoT renders an enormous amount of data from various sensors. On the other hand, ML opens up insight hidden in the acquired data....

Smart Display Board based on IoT and Google Firebase

Introduction In this tutorial, we are going to build a Smart Display Board based on IoT and Google Firebase by using NodeMCU8266 (or you can even use NodeMCU32) and LCD. Generally, in shops, hotels, offices, railway stations, notice/ display boards are used. They are...

Smart Gardening System – GO GREEN Project

Automation of farm activities can transform agricultural domain from being manual into a dynamic field to yield higher production with less human intervention. The project Green is developed to manage farms using modern information and communication technologies....