Type-Safe Next.js App Router: Server Actions, Params, and Error Handling That Actually Scale
App Router introduced async params, server actions, and new patterns for forms and mutations — and TypeScript support for all of it has sharp edges. Here are the patterns I use to keep things type-safe without fighting the framework.
App Router changed how data flows through a Next.js app. Server actions replaced API routes for most mutations. Params became async. searchParams arrived untyped. And TypeScript support for all of it has real sharp edges that aren't obvious until you hit them.
These are the patterns I use across production apps to keep server actions, params, and error handling type-safe without fighting the framework.
Type Your Server Action Returns as a Discriminated Union#
Server actions that return void or throw on failure make form handling awkward. The pattern I use everywhere is a discriminated union:
type ActionResult<T = void> =
| { success: true; data: T }
| { success: false; error: string };
Every server action returns this type, never throws:
"use server";
export async function createItem(
input: unknown
): Promise<ActionResult<{ id: string }>> {
const parsed = CreateItemSchema.safeParse(input);
if (!parsed.success) {
return { success: false, error: parsed.error.errors[0]. };
}
{
item = db..(parsed.);
{ : , : { : item. } };
} {
{ : , : };
}
}
Freelance
¿Necesitas ayuda con esto?
Puedo ayudarte con migraciones, nuevos productos y rendimiento web.
Contactar →