Next.js Route Handlers in TypeScript: Comprehensive Guide
Next.js provides built-in support for route handling, allowing you to manage different types of HTTP requests (GET, POST, PATCH, DELETE) within the app
directory. When using TypeScript, you can leverage strong typing to ensure type safety and better development experience.
Here, we’ll explore the various aspects of Next.js Route Handlers using TypeScript, complete with explanations and code examples.
1. Route Handlers in Next.js
In TypeScript, route handlers are defined similarly to JavaScript, but with type annotations to ensure type safety. Each handler is placed in the app
directory, usually under an api
folder, and the filename follows the route.ts
naming convention.
Example:
// app/api/users/route.ts
export async function GET(request: Request): Promise<Response> {
return new Response('Hello, users!');
}
2. Handling GET Requests
The GET
method is used to retrieve data from the server. In TypeScript, we type the request as Request
and return a Response
.
export async function GET(request: Request): Promise<Response> {
const users = [{ id: 1, name: "John Doe" }, { id: 2, name: "Jane Doe" }];
return new Response(JSON.stringify(users), {
status: 200,
headers: {
'Content-Type': 'application/json',
},
});
}
3. Handling POST Requests
The POST
method is used to send data to the server. In the route handler, you can extract and process the body content of the request.
export async function POST(request: Request): Promise<Response> {
const body = await request.json(); // Extract JSON data from the request body
// Simulate saving the data
return new Response(JSON.stringify({ message: 'User created', body }), {
status: 201,
headers: {
'Content-Type': 'application/json',
},
});
}
4. Dynamic Route Handlers
Dynamic routes in Next.js allow you to handle requests with variable parameters in the URL. These dynamic parameters can be accessed from the request object.
// app/api/users/[id]/route.ts
export async function GET(request: Request, { params }: { params: { id: string } }): Promise<Response> {
const userId = params.id;
return new Response(`User ID: ${userId}`, {
status: 200,
});
}
5. Handling PATCH Requests
The PATCH
method is used to update specific fields in a resource. You can process the request body and perform partial updates.
export async function PATCH(request: Request): Promise<Response> {
const body = await request.json();
// Simulate updating user data
return new Response(JSON.stringify({ message: 'User updated', body }), {
status: 200,
headers: {
'Content-Type': 'application/json',
},
});
}
6. Handling DELETE Requests
The DELETE
method is used to remove resources. Here's how to handle a DELETE request in Next.js with TypeScript.
export async function DELETE(request: Request): Promise<Response> {
// Simulate deleting a resource
return new Response('User deleted', {
status: 200,
});
}
7. URL Query Parameters
To access query parameters in Next.js route handlers, use the URLSearchParams
API available on the request object.
export async function GET(request: Request): Promise<Response> {
const { searchParams } = new URL(request.url);
const userId = searchParams.get('id');
return new Response(`Query param userId: ${userId}`, {
status: 200,
});
}
8. Redirects in Route Handlers
You can perform redirects in route handlers by returning a Response
object with a status
of 302 or 301 and a Location
header.
export async function GET(request: Request): Promise<Response> {
return new Response(null, {
status: 302,
headers: {
Location: '/new-url',
},
});
}
9. Headers in Route Handlers
You can set custom headers in the response using the headers
option in the Response
constructor.
export async function GET(request: Request): Promise<Response> {
return new Response('Hello, world!', {
status: 200,
headers: {
'X-Custom-Header': 'CustomHeaderValue',
},
});
}
10. Cookies in Route Handlers
Cookies can be managed through the Headers
API. Here’s how to set cookies in a response.
export async function GET(request: Request): Promise<Response> {
const response = new Response('Cookie Set', {
status: 200,
});
response.headers.append('Set-Cookie', 'token=abc123; HttpOnly; Path=/');
return response;
}
11. Caching in Route Handlers
You can control caching behavior by setting appropriate cache control headers.
export async function GET(request: Request): Promise<Response> {
return new Response('Cached Response', {
status: 200,
headers: {
'Cache-Control': 'public, max-age=3600', // Cache for 1 hour
},
});
}
12. Middleware in Route Handlers
Next.js supports middleware that can run before the route handlers. You can use middleware for tasks like authentication or logging.
// app/middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const token = request.cookies.get('token');
if (!token) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
Conclusion
Next.js route handlers in TypeScript offer a clean and efficient way to manage various types of HTTP requests, from handling simple GET requests to managing dynamic routes, redirects, and cookies. With TypeScript’s type safety, you can write robust, predictable server-side logic in your Next.js applications.