Next.js 16 Type Safety: Async PageProps & Typed Routes
Source: Dev.to
Introduction
Next.js has quietly become one of the most type‑safe full‑stack frameworks, yet many teams only use a fraction of its capabilities. This post walks through practical, production‑ready type‑safety features in the modern App Router, including:
- TypeScript checker enhancements
- Statically typed links
- Route‑aware type helpers
- Auto‑complete for environment variables
- Typed
NextRequestandNextResponse
This is not a beginner guide; it focuses on features that prevent bugs in real‑world applications.
TypeScript Checker
Next.js ships with a custom TypeScript plugin that extends the default tsc checks. It understands Next.js‑specific concepts such as:
- File‑based routing
- Server vs. client components
- Metadata APIs
- Layout and page conventions
Enabling the plugin in VS Code
- Open the Command Palette (
Ctrl/Cmd + Shift + P). - Search for TypeScript: Select TypeScript Version.
- Choose Use Workspace Version.
VS Code will now pick up the Next.js‑specific type rules automatically via next-env.d.ts, giving you IntelliSense and in‑context documentation for APIs like metadata and caching options.
Additional checks provided by the plugin
- Correct usage of the
"use client"directive. - Prevention of client‑only hooks (e.g.,
useState) in Server Components. - Detection of invalid exports in
page.tsx,layout.tsx, androute.ts.
Statically Typed Links
Next.js can generate statically typed routes to eliminate typos and invalid navigation.
Enable typed routes
// next.config.ts
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
typedRoutes: true,
};
export default nextConfig;
When typedRoutes is enabled, Next.js creates route definitions inside .next/types. TypeScript then validates links and navigation at compile time, providing:
- Compile‑time errors for invalid routes
- Safer refactors
- IntelliSense that suggests only valid paths
Route‑Aware Helpers
The App Router automatically generates global helpers (no imports required) during next dev, next build, or via next typegen.
Available helpers
PageProps– typed props for page componentsLayoutProps– typed props for layout componentsRouteContext– typed context for API routes
Using PageProps
// pages/details/[slotId]/page.tsx
export default function Details({
params,
searchParams,
}: {
params: { slotId: string };
searchParams: { name?: string };
}) {
const { slotId } = params;
const { name } = searchParams;
return (
<>
Slot: {slotId}
<br />
Name: {name}
</>
);
}
A more concise, type‑safe version:
export default async function Details(
props: PageProps
) {
const { slotId } = await props.params;
const { name } = await props.searchParams;
return (
<>
Slot: {slotId}
<br />
Name: {name}
</>
);
}
Using LayoutProps
import type { ReactNode } from "react";
export default function RootLayout({
children,
}: {
children: ReactNode;
}) {
return (
<>
{children}
</>
);
}
Typed version:
export default function RootLayout(
props: LayoutProps
) {
return (
<>
{props.children}
</>
);
}
Using RouteContext in API routes
import { NextRequest, NextResponse } from "next/server";
export async function GET(
_request: NextRequest,
ctx: RouteContext
) {
const { id } = await ctx.params;
return NextResponse.json({ msg: `Hello, ${id}!` });
}
RouteContext provides full IntelliSense for route parameters, eliminating manual typing.
Typed NextRequest and NextResponse
Both classes extend the standard Web APIs with Next‑specific helpers.
NextRequest
- Typed cookies
- Parsed URLs via
nextUrl - Middleware‑friendly helpers
NextResponse
json()– send JSON responsesredirect()– perform redirects- Cookie helpers
- Edge‑friendly APIs
Example:
import { NextRequest, NextResponse } from "next/server";
export async function GET(_request: NextRequest) {
return NextResponse.json({ msg: "Hello!!!" });
}
Conclusion
Next.js type safety isn’t about writing more types; it’s about using TypeScript as a guardrail that reduces bugs without adding overhead. By enabling the built‑in TypeScript plugin, typed routes, and route‑aware helpers, you get compile‑time guarantees and richer editor support throughout your application.
Reference: Next.js – TypeScript documentation