Write reusable, type-safe functions and data structures with generics.
Without generics, to write a function that works with any type you'd use any — which throws away type safety:
function first(arr: any[]): any {
return arr[0];
}
TypeScript can't tell you what type first([1, 2, 3]) returns. It's any.
A type parameter (written <T>) acts as a placeholder that gets filled in at call time:
function first<T>(arr: T[]): T {
return arr[0];
}
const n = first([1, 2, 3]); // n is number ✓
const s = first(["a", "b"]); // s is string ✓
TypeScript infers T automatically — you rarely need to write it explicitly.
function identity<T>(value: T): T {
return value;
}
function pair<A, B>(a: A, b: B): [A, B] {
return [a, b];
}
Use extends to restrict what T can be:
function getLength<T extends { length: number }>(item: T): number {
return item.length;
}
getLength("hello"); // 5
getLength([1, 2, 3]); // 3
getLength(42); // ❌ Error: number has no .length
identity<T> that takes a value and returns it unchanged.last<T> that takes a T[] array and returns the last element (or undefined if empty).filterTruthy<T> that takes a T[] and returns a new array with all falsy values removed.// 1. Export identity<T>(value: T): T // 2. Export last<T>(arr: T[]): T | undefined // 3. Export filterTruthy<T>(arr: T[]): T[]