Skip to Content
NewNext-TS-API 1.0 is releasedGet started →
DocsCore Concepts

Core Concepts

Next-TS-API is built around several core concepts that work together to provide end-to-end type safety for your Next.js API routes.

Type Generation

Next-TS-API automatically generates TypeScript types for your API routes by analyzing your route handlers. This includes:

  • Request body types
  • Response payload types
  • Query parameters
  • Path parameters

The generated types are stored in types/next-ts-api.ts and are automatically updated when you make changes to your API routes.

Route Handlers

Route handlers in Next-TS-API are enhanced versions of Next.js route handlers with built-in type safety:

import { NextApiRequest } from 'next-ts-api'; // POST handler with typed request body export async function POST( request: NextApiRequest<{ title: string; completed: boolean; }> ) { const { title, completed } = await request.json(); return Response.json({ success: true, data: { title, completed } }); }

Type-Safe API Client

The API client provides type-safe access to your API routes:

import { createNextFetchApi } from "next-ts-api"; import { type ApiRoutes } from "../types/next-ts-api"; // Create a type-safe API client export const api = createNextFetchApi<ApiRoutes>(); // All API calls are now type-safe const response = await api('users', { method: 'POST', body: { name: 'John', // Type checked! email: 'john@example.com' // Type checked! } });

File Uploads & Form Data

For multipart requests, declare the field shape on the handler just like a JSON body, then read it with the typed request.formData():

// app/api/upload/route.ts import { NextApiRequest } from 'next-ts-api'; import { NextResponse } from 'next/server'; export async function POST( request: NextApiRequest<{ file: File; name: string }> ) { const data = await request.formData(); const file = data.get('file'); const name = data.get('name'); if (!(file instanceof File)) { return NextResponse.json({ error: 'file required' }, { status: 400 }); } return NextResponse.json({ name, size: file.size }); }

On the client, use form instead of body. The client builds the FormData and sets the correct headers for you:

const response = await api('upload', { method: 'POST', form: { file: new File(['hello'], 'hello.txt', { type: 'text/plain' }), name: 'greeting', // Type checked against the handler! }, }); const data = await response.json();

Best Practices

  1. Always Import from next-ts-api:

    import { NextApiRequest } from 'next-ts-api'; // NOT from 'next/types'
  2. Use Type Annotations:

    // Good - explicit types export async function POST( request: NextApiRequest<CreateTodoInput> ) { } // Avoid - implicit any export async function POST(request) { }
  3. Leverage Generated Types:

    import { type ApiRoutes } from "../types/next-ts-api"; // Use throughout your application

Next Steps

Last updated on