Generics
Intro to Generics
Generics are one of TypeScript's most powerful featuresβand a cornerstone of
functional programming. They let you write reusable transformations that
work with multiple types while maintaining type safety.
// Without generics - only works with numbers
function firstNumber(arr: Array<number>): number | undefined {
return arr[0]
}
// With generics - works with ANY type
function first<Item>(arr: Array<Item>): Item | undefined {
return arr[0]
}
first([1, 2, 3]) // Item is number, returns number | undefined
first(['a', 'b']) // Item is string, returns string | undefined
The Problem Generics Solve
Without generics, you'd need to either:
- Write duplicate code for each type
- Use
anyand lose type safety
// Bad: Duplicated code
function firstString(arr: Array<string>): string | undefined { ... }
function firstNumber(arr: Array<number>): number | undefined { ... }
function firstUser(arr: Array<User>): User | undefined { ... }
// Bad: Loses type safety
function first(arr: Array<any>): any { ... }
// Good: Generic - type-safe and reusable
function first<Item>(arr: Array<Item>): Item | undefined { ... }
Generics Are Everywhere
You've already been using generics!
Array<Item>, Promise<ResponseText>, and many more:const numbers: Array<number> = [1, 2, 3]
const promise: Promise<ResponseText> = fetch('/api').then((r) => r.text())
Think of generics as type-level functionsβjust like functions transform
values, generic types transform types.
Array<Item> is a function that takes a
type Item and returns the type "array of Item". This is the foundation of
functional type-level programming.In this exercise, you'll learn to write and use generic code.