Back to Blog
components/data-table.tsx
types/api.ts
lib/actions/project.ts
February 20, 20261 min read
Mastering TypeScript: Advanced Patterns for React Developers
Explore advanced TypeScript patterns including generic components, discriminated unions, and type-safe API layers for modern React applications.
typescript
react
patterns
Introduction
TypeScript has become the standard for modern React development. In this post, we'll explore advanced patterns that will level up your TypeScript skills.
Generic Components
One of the most powerful TypeScript patterns is creating generic components:
interface DataTableProps<T> {
data: T[];
columns: {
key: keyof T;
label: string;
render?: (value: T[keyof T], item: T) => React.ReactNode;
}[];
onRowClick?: (item: T) => void;
}
export function DataTable<T extends Record<string, unknown>>({
data,
columns,
onRowClick,
}: DataTableProps<T>) {
return (
<table>
<thead>
<tr>
{columns.map((col) => (
<th key={String(col.key)}>{col.label}</th>
))}
</tr>
</thead>
<tbody>
{data.map((item, i) => (
<tr key={i} onClick={() => onRowClick?.(item)}>
{columns.map((col) => (
<td key={String(col.key)}>
{col.render
? col.render(item[col.key], item)
: String(item[col.key])}
</td>
))}
</tr>
))}
</tbody>
</table>
);
}Discriminated Unions
Discriminated unions are perfect for handling different states:
type ApiState<T> =
| { status: "idle" }
| { status: "loading" }
| { status: "success"; data: T }
| { status: "error"; error: string };Type-Safe Server Actions
With Next.js Server Actions, we can create fully type-safe mutations:
"use server";
import { z } from "zod";
const createProjectSchema = z.object({
title: z.string().min(1),
description: z.string().min(10),
techStack: z.array(z.string()),
});
export async function createProject(
formData: z.infer<typeof createProjectSchema>
) {
const validated = createProjectSchema.parse(formData);
// ... create in database
}Conclusion
These patterns create a robust foundation for any React + TypeScript project. The key is leveraging the type system to catch errors at compile time rather than runtime.