Master TypeScript generics to build flexible, reusable functions and interfaces without sacrificing type safety.
Discover how TypeScript infers types automatically and how let versus const declarations shape wide types versus narrow literal types.
Functions take arguments to handle reusable data values. Generics take type parameters (<T>) to handle reusable data types!
Without generics, you either have to duplicate code for every data type or use any (which destroys type safety). Generics capture the exact argument type and pass it through to return values.
Use angle brackets (<T>) to define a generic type parameter:
// Generic identity function: T captures input type
function identity<T>(arg: T): T {
return arg;
}
const numResult = identity<number>(42); // Explicit T = number
const strResult = identity("DevLoom"); // Inferred T = string (Hovering shows string!)
// Generic Array Helper
function getFirstItem<T>(list: T[]): T | undefined {
return list[0];
}
const firstNumber = getFirstItem([10, 20, 30]); // Inferred return type: number | undefined
const firstString = getFirstItem(["a", "b"]); // Inferred return type: string | undefined
[ Input Argument ] ──> "DevLoom" (string)
│
▼
[ Generic Parameter T ] ──> T = string
│
▼
[ Return Type T ] ──> Returns string with 100% type safety!
interface ApiResponse<DataPayload> {
status: number;
data: DataPayload;
}
type UserData = { name: string; email: string };
type UserApiResponse = ApiResponse<UserData>;
<T> to a function that doesn't return or relate T to other parameters adds unnecessary complexity.Use generics to build reusable containers and utilities. Next, let's explore Generic Constraints (extends)!