TypeScript Generic Constraints (original) (raw)
Last Updated : 04 Sep, 2024
In TypeScript, generic constraints restrict the types that can be used with a generic type by using the extends keyword. This ensures that the generic type adheres to a specific structure or interface, allowing access to certain properties or methods within the generic type.
What are Generic Constraints?
- TypeScript Generics allows us to write reusable code by working with different data types. We can create functions, classes, or interfaces that can work with different data types.
- Generics are defined as ****** and This type of T is used to define the type of function arguments, return values, etc.
- Generic Constraints are used to specify limits to the types that can be used with generic type parameters.
- This results in type checking and these conditions ensure that variables have a certain type of value before they are used in the context.
- This check minimizes the occurrence of runtime errors.
Syntax:
function genericConstraintFunction(param: T): void { // ... }
**Where-
- T is the generic type parameter.
- **`extends` GenericConstraintType specifies the constraint that Type T should be extending GenericConstraintType type.
**Example 1: In this example, the Sports interface has a name property. The printSportName function uses extends to ensure its argument conforms to the Sports type before execution.
JavaScript `
// Define Sports interface with a name property interface Sports { name: string; }
// Function to print sport name, ensuring T extends Sports function printSportName(sport: T): void { console.log(sport.name); }
// Create a sport object of type Sports let sport: Sports = { name: "baseball" };
// Call function with sport object printSportName(sport);
`
**Output:
baseball
**Example 2: In this example, we use extends keyof to ensure that the generic type parameter K is a key of type T. This enforces that K is a valid property of T.
JavaScript ``
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.
JavaScript ``
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(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