TypeScript Generics
Job-ready Online Courses: Dive into Knowledge. Learn More!
A superset of JavaScript called TypeScript gives the language static typing. With TypeScript, developers can write code with fewer bugs and better maintainability. TypeScript generics take this further, allowing for even greater code reusability and flexibility. In this article, we’ll cover the basics of TypeScript generics, including generic constraints, generic interfaces, and generic classes.
What Are Generics?
Generics are a way to write code that can work with various types. For example, let’s say you have a function that returns the first element of an array:
function DataFlair_firstElement(arr: any[]): any {
return arr[0];
}
This function works fine, but it’s not very type-safe. It takes an array of any type and returns an element of any type. We can improve this function using generics:
function DataFlair_firstElement<T>(arr: T[]): T {
return arr[0];
}
The <T> syntax declares a type parameter. When we call this function, we can specify the type of the array:
const numArray = [1, 2, 3]; const firstNum = DataFlair_firstElement(numArray); const strArray = ['a', 'b', 'c']; const firstStr = DataFlair_firstElement(strArray);
Using generics, we’ve made our function type-safe and reusable with different arrays.
TypeScript Generic Constraints
Sometimes we want to restrict the types that can be used with generics. For example, let’s say we have a function that adds two numbers:
function DataFlair_add(a: number, b: number): number {
return a + b;
}
We can make this function generic to work with other numeric types:
function DataFlair_add<T extends number>(a: T, b: T): T {
return a + b;
}
The <T extends number> syntax is a generic constraint. It restricts the type parameter to be a subtype of the number type.
Now we can call this function with different numeric types:
const numSum = DataFlair_add(1, 2); // numSum is type number const bigIntSum = DataFlair_add(100n, 200n); // bigIntSum is type bigint
However, if we try to call this function with a non-numeric type, we’ll get a compile-time error:
const strSum = DataFlairadd('a', 'b');
TypeScript Generic Interfaces
Interfaces in TypeScript are a way to define a contract for an object. We can make interfaces generic to work with different types of objects.
For example, let’s say we have an interface for a point in 2D space:
interface DataFlair_Point {
x: number;
y: number;
}
We can make this interface generic to work with different types of coordinates:
interface DataFlair_Point<T> {
x: T;
y: T;
}
Now we can create points with different types of coordinates:
const intPoint: DataFlair_Point<number> = { x: 1, y: 2 };
const strPoint: DataFlair_Point<string> = { x: 'a', y: 'b' };
TypeScript Generic Classes
Classes in TypeScript are a way to define a blueprint for an object. We can make classes generic to work with different types of objects.
For example, let’s say we have a class for a DataFlair_stack:
class DataFlair_Stack<T> {
private elements: T[] = [];
push(element: T) {
this.elements.push(element);
}
pop(): T {
return this.elements.pop();
}
}
The <T> syntax declares a type parameter for the DataFlair_stack. We can create a stack with different types of elements:
const numStack = new DataFlair_Stack<number>();
numStack.push(1);
numStack.push(2);
const num1 = numStack.pop(); // num1 is type number
const num2 = numStack.pop(); // num2 is type number
const strStack = new DataFlair_Stack<string>();
strStack.push('a');
strStack.push('b');
const str1 = strStack.pop(); // str1 is type string
const str2 = strStack.pop(); // str2 is type string
By making the stack class generic, we’ve made it reusable with different types of elements.
Type aliases in TypeScript
Type aliases in TypeScript are a feature that allows you to create a new name for a type. They can be used to simplify complex types, improve code readability and maintainability, and make type definitions more reusable.
Type aliases are created using the type keyword, followed by a name and an equal sign, followed by the type that the alias will represent. For example, the following code creates a type alias DataFlair_Person for an object type with name and age properties:
type DataFlair_Person = {
name: string;
age: number;
};
Once the type alias is defined, it can be used anywhere a type is expected. For example, you could use it to define a function parameter like this:
function greet(person: DataFlair_Person) {
console.log(`Hello, ${person.name}!`);
}
You can also create type aliases for more complex types, including union, intersection, and function types. Type aliases can also be generic, allowing you to create reusable type definitions that can be used with different types.
Overall, type aliases are a powerful tool that can help improve code readability and maintainability in TypeScript projects.
Extend Keyword in TypeScript
In TypeScript, you can use the extends keyword to create generic types that extend or inherit from other types. This allows you to define more specific types that include additional properties or methods while still maintaining the original type’s structure.
Here’s an example of using extends in generics:
interface DataFlair_Shape {
area: number;
}
interface Square extends DataFlair_Shape {
sideLength: number;
}
function calculateArea<T extends DataFlair_Shape>(shape: T): number {
return shape.area;
}
const square: Square = { area: 16, sideLength: 4 };
const area = calculateArea(square); // returns 16
Output –
16
This example defines an interface DataFlair_Shape that includes a single property area. We then define another interface Square that extends DataFlair_Shape and adds a property sideLength.
We then define a function calculateArea that takes a generic type T that extends DataFlair_Shape and returns its area property.
Finally, we create an instance of Square and pass it to calculateArea, which correctly returns its area property.
Using extends in generics allows you to create more specific types that inherit properties and methods from more generic types. This can help improve code organization, reduce duplication, and increase type safety in TypeScript projects.
Prerequisites
Before using generics in TypeScript, it’s important to understand basic TypeScript syntax, including interfaces, classes, and functions. You should also be familiar with TypeScript’s type system, including basic types like string, number, boolean, and any, and more advanced types like union and intersection types.
Once you have a good foundation in TypeScript, you can learn about generics. Generics allow you to create reusable code that can work with various data types. They’re particularly useful for creating functions and classes that work with arrays or collections of data.
To use generics in TypeScript, you need to define a generic type parameter. You can use this placeholder type throughout your code to represent any data type. You define the generic type parameter using angle brackets (<>) and a single uppercase letter, like T.
Here’s an example of a generic function that takes an array of values of any type and returns the first value in the array:
function DataFlair_first<T>(array: T[]): T | undefined {
return array[0];
}
In this example, we define a generic type parameter T, which we use to represent the data type in the array. We then use the [] syntax to indicate that the function takes an array of values of type T. The function returns the first value in the array, which has the same type as the array elements (T).
Prerequisites for using generics in TypeScript include a strong understanding of basic TypeScript syntax and the ability to create and work with interfaces, classes, and functions. Once you have these skills, you can learn about generics and how to use them to create reusable, type-safe code.
Creating Conditional Types with Generics
In TypeScript, conditional types allow you to define types that depend on a condition or a set of conditions. Conditional types are created using the extends keyword and can be used to create more specific types based on the properties or values of other types.
Here’s an example of a conditional type that creates a more specific type based on the properties of another type:
type DataFlair_HasName<T> = T extends { name: string } ? true : false;
interface Person {
name: string;
age: number;
}
const personHasName: DataFlair_HasName<Person> = true;
In this example, we define a type DataFlair_HasName that takes a generic type parameter T. We then use the extends keyword to create a condition that checks if T has a property name of the type string. If the condition is true, the type resolves to true; otherwise, it resolves to false.
We then define an interface Person with a name property of type string and an age property of type number. We create a variable personHasName that is of type DataFlair_HasName<Person>. Since Person has a name property, personHasName is of type true.
Using conditional types with generics can be a powerful tool in TypeScript, allowing you to create more specific types based on the properties or values of other types. This can help improve type safety and code readability in TypeScript projects.
Advantage of Generics in TypeScript
Generics in TypeScript has several advantages that make them a powerful tool for creating reusable, type-safe code:
1. Reusability: Generics allow you to create code that can work with a variety of different data types. This makes your code more reusable and reduces the need for duplication.
2. Type safety: By using generics, you can ensure that your code is type-safe. This means that you can catch type errors at compile time rather than at runtime, saving you time and improving your code’s overall quality.
3. Code readability: Generics can make your code more readable by clearly indicating the data types your code is working with. This can help make your code easier to understand and maintain.
4. Flexibility: Generics can create a wide range of data structures and algorithms, from simple functions that work with arrays to complex class hierarchies that handle complex data types.
Overall, the advantages of generics in TypeScript make them an essential tool for creating robust, scalable, and maintainable code. Whether you’re working on a small project or a large enterprise application, generics can help you write better code that is easier to read, maintain, and debug.
Conclusion
TypeScript generic is a powerful tool for writing reusable and flexible code. They allow us to write functions, interfaces, and classes that work with various types. We can use generic constraints to restrict the types used with generics and generic interfaces. and classes. It is to define contracts and blueprints for objects of different types.
Using TypeScript generics, we can write type-safe code that is easier to maintain and extend. If you still need to use generics in your TypeScript code, try them and see how they can improve your code reusability and flexibility.
If you are Happy with DataFlair, do not forget to make us happy with your positive feedback on Google

