Generics are one of the most powerful and heavily used features in TypeScript.
They allow you to write reusable code that can work with a variety of types.
Instead of hardcoding a type like string, you use a variable (like <T>).
This preserves the strict type information without losing flexibility.
Without generics, you would have to use any to make a function highly reusable.
Using any destroys all static type checking and IntelliSense in your editor.
Generics solve this by dynamically locking in the type at the exact moment of execution.
// T acts as a placeholder for the actual type
function identity<T>(arg: T): T {
return arg;
}
let strOutput = identity<string>("Hello");
let numOutput = identity<number>(100);
console.log(strOutput, numOutput);
Generics are not just for functions; they are incredibly useful for Interfaces too.
This is widely used when wrapping HTTP API responses that contain dynamic payload data.
It allows your data wrappers to be universally applied across your entire project.
interface ApiResponse<Data> {
status: number;
message: string;
data: Data; // This will adapt to whatever type is passed!
}
let userRes: ApiResponse<{ name: string }> = {
status: 200, message: "OK", data: { name: "Akash" }
};
console.log("API Response:", userRes);
Writing reusable code shrinks your bundle sizes, improving page load speeds.
Faster web pages lead to significantly higher retention and better SEO metrics.
Generics help keep your source code extremely lightweight and deeply maintainable.
class Box<T> {
contents: T;
constructor(value: T) { this.contents = value; }
}
const stringBox = new Box<string>("A secret");
console.log("Box contains:", stringBox.contents);
Which syntax is used to define a Generic type variable in TypeScript?
Generics can look intimidating at first, but they are an absolute necessity for modern TS.
They provide the ultimate balance between strict typing and code reusability.
Next, we will see how TypeScript uses generics natively via Utility Types!