Open In App

TypeScript Generic Constraints

In this article, we are going to discuss Generic Constraints. TypeScript is known for its strong typing system. In TypeScript, If we require more control over our generic types, we use TypeScript Generic Constraints. We use Generic type constraints to specify limits on the types for generic type parameters. This helps us to determine that generic types extend or implement a specific type or contain specific properties.

What are Generic Constraints?

Syntax:

function genericConstraintFunction<T extends GenericConstraintType>(param: T): void {
// ...
}

Where-



Example 1: In this example consider we have an interface of sports and it contains a property called name of type string. We created a variable sport of type Sports and assigned the name “baseball”. We have a function called printSportName which expects an argument of type T. Now, to ensure that this Type T is of type Sports, we use the keyword ‘extends’ with Sports. This checks, if the arguments passed through the function, are of type Sports before the function execution.

 






interface Sports {
    name: string;
}
  
function printSportName<T extends Sports>(sport: T): void {
    console.log(sport.name);
}
let sport: Sports = { name: "baseball" };
printSportName(sport);

Output:

baseball

Example 2: In this example , let learn how we use Property Key Constraints. This ensures generic type parameter to have certain properties or keys. This example is an extension of the example explained above. Here, we use ‘extends keyof’ to ensure that the value passed through K is of Type T and is a Key/Property of Type T.




interface Sports {
    name: string;
    players: number;
}
  
function getNumberOfPlayers<T extends Sports, K extends keyof T>
(sport: T, players: K): T[K] {
    return sport[players];
}
  
let sport: Sports = { name: "baseball", players: 9 };
  
// 'players' is inferred as a number
let players: number = getNumberOfPlayers(sport, 'players');
console.log(`Number of Players are : ${players}`);

Output:

Number of Players are : 9

Example 3: In this example, we ensure that the generic type parameter class object implements a specific interface.




interface Sports {
    name: string;
    players: number;
    getNumberOfGloves(): number;
}
  
class Baseball implements Sports {
    constructor(public name: string, public players: number) { }
  
    getNumberOfGloves(): number {
        return this.players * 2;
    }
}
  
function getNumberOfGloves<T extends Sports>(sport: T): void {
    console.log(`Number of Gloves required are : 
        ${sport.getNumberOfGloves()}`);
}
  
let baseball = new Baseball("baseball", 9);
getNumberOfGloves(baseball);

Output:

Number of Gloves required are : 18

Article Tags :