TypeScript Tutorial: Generics
Write reusable, type-safe functions and data structures with generics.
The Problem Generics Solve
Without generics you'd need separate functions for every type:
```typescript
function firstNumber(arr: number[]): number { return arr[0]; }
function firstString(arr: string[]): string { return arr[0]; }
// With generics — one function, any type:
function first<T>(arr: T[]): T {
return arr[0];
}
first([1, 2, 3]); // returns number
first(["a", "b", "c"]); // returns string
```
`T` is a **type parameter** — a placeholder filled in when the function is called.
---
Generic Functions
```typescript
function identity<T>(value: T): T {
return value;
}
function pair<A, B>(a: A, b: B): [A, B] {
return [a, b];
}
console.log(identity(42)); // 42
console.log(pair("hello", true)); // ["hello", true]
```
---
Generic Interfaces
```typescript
interface Box<T> {
value: T;
transform<U>(fn: (v: T) => U): Box<U>;
}
```
---
Generic Constraints
Use `extends` to restrict what types a generic can be:
```typescript
interface HasLength {
length: number;
}
function logLength<T extends HasLength>(item: T): void {
console.log(item.length);
}
logLength("hello"); // ✓ strings have .length
logLength([1, 2, 3]); // ✓ arrays have .length
logLength({ length: 5 }); // ✓ object with length
logLength(42); // ✗ Error: number has no length
```
---
keyof and Generic Lookup
```typescript
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const user = { name: "Alice", age: 30 };
getProperty(user, "name"); // string ✓
getProperty(user, "age"); // number ✓
getProperty(user, "foo"); // ✗ Error: "foo" not in user
```
---
What's Next?
Next: **Classes** — TypeScript's class system with access modifiers, abstract classes, and interfaces.
What you'll learn in this TypeScript generics tutorial
This interactive TypeScript tutorial has 12 hands-on exercises. Estimated time: 15 minutes.
- Your first generic function — A generic function uses `<T>` as a type parameter filled in at call time. TypeScript infers `T` from the argument — no e…
- Generic collections — typed containers — Generic classes create reusable containers that work with any type while maintaining type safety.
- Generic API response wrapper — Wrap every API response in a generic type so callers know exactly what data type they'll receive.
- Generic constraints — limit what T can be — `T extends SomeType` restricts the allowed types. This lets you safely access properties guaranteed by the constraint.
- Multiple type parameters — A generic function can have multiple independent type parameters, each inferred separately.
- Generic utility functions — Generic functions make utility code reusable across all types. Here are common generic utilities used in real codebases.
- Generic interfaces — reusable type shapes — Interfaces can have type parameters, enabling reusable contracts that work across different data types.
- Generic conditional defaults — Generic functions can use conditional types to provide intelligent defaults based on what type is provided.
- Variadic generics — tuple types — Generics can capture the types of variadic arguments using tuple rest types. This enables precise typing for functions t…
- Generic error handling — typed Result — A generic `Result<T, E>` type encapsulates either a successful value or an error. Callers must handle both cases before …
- Generic higher-order functions — Higher-order functions that create other functions can preserve full type safety using generics.
- Generic constraints with keyof — `keyof T` produces a union of all property names of `T`. Combined with generics, it enables type-safe property access.
TypeScript Generics concepts covered
- The Problem Generics Solve
- Generic Functions
- Generic Interfaces
- Generic Constraints
- keyof and Generic Lookup
- What's Next?