TypeScript Generics for React Engineers: A Practical Guide
TypeScriptReactFrontend

TypeScript Generics for React Engineers: A Practical Guide

The 6 generic patterns I use weekly on React + Next.js codebases — typed hooks, polymorphic components, discriminated unions, infer, constraints — without the academic noise.

HJ
Hassan Javed
May 2026
10 min read

Generics are not academic

When React engineers ask me "do I really need TypeScript generics?" the answer is almost always: you're already using them, you just haven't named them yet.

Every useState(...), every array map with inferred types, every fetch typed with a return shape — that's generics doing the work. You just lean on inference. When inference isn't enough, knowing the explicit patterns saves hours.

This post is the 6 patterns I reach for on every React or Next.js codebase, in roughly the order you'll need them.

Pattern 1: Typed custom hooks

The most common case. A hook returns data of a shape that depends on what the caller fetches.

A custom useFetch(url) hook can be parameterized with the return type. The caller writes useFetch('/api/me') and gets fully typed data: User | null downstream.

Without the generic, data is unknown or any. With it, the caller's destructuring is autocompleted.

Pattern 2: Constrained generics

When the generic type must satisfy some shape. For example, a sortBy(items, key) utility that operates over any object with an id field, using keyof T to narrow the key argument to a real property name.

The extends { id: string } is a constraint. T can be any object as long as it has an id. This pattern is gold for utility functions over collections of "things with an id" — orders, users, products, anything.

Pattern 3: Polymorphic components

The "as" prop pattern — a component that can render as different HTML elements. For example a

Related Reads

You might also like