When working with Next.js 15 API routes, you might encounter a TypeScript error stating that your route has an invalid export. Specifically, you might see this error during the build:
Command line
Creating an optimized production build ...
â Compiled successfully
Linting and checking validity of types ..Failed to compile.
src/app/api/articles/[slug]/route.ts
Type error: Route "src/app/api/articles/[slug]/route.ts" has an invalid "GET" export:
Type "Props" is not a valid type for the function's second argument.
This error occurs when using the traditional approach to typing route parameters:
src/app/api/articles/[slug]/route.ts
TypeScript
1// ð« This approach no longer works in Next.js 15
2
3import { NextRequest } from 'next/server'
4import { getArticleBySlug } from '@/library/articles'
5
6type Props = {
7 params: {
8 slug: string
9 }
10}
11
12export async function GET(
13 req: NextRequest,
14 props: Props
15): Promise<NextResponse> {
16 try {
17 const article = await getArticleBySlug(
18 props.params.slug
19 )
20 // ...rest of the handler
21 } catch (error) {
22 // error handling
23 }
24}
The Solution
In Next.js 15, route parameters are now handled as a Promise. Here's the correct way to type and handle them:
src/app/api/articles/[slug]/route.ts
TypeScript
1// â
The correct approach for Next.js 15
2
3import { NextRequest, NextResponse } from 'next/server'
4import { getArticleBySlug } from '@/library/articles'
5
6export async function GET(
7 request: NextRequest,
8 { params }: { params: Promise<{ slug: string }> }
9): Promise<NextResponse> {
10 try {
11 const { slug } = await params
12 // ...rest of the handler
13 } catch (error) {
14 // error handling
15 }
16}
Key changes explained
- Promise Type: The
params
object is now typed as a Promise:route.tsTypeScript{ params: Promise<{ slug: string }> }
- Await Parameters: You must await the
params
before accessing any parameter properties:route.tsTypeScript// Destructure specific parameters const { slug } = await params // Get all resolved parameters at once const resolvedParams = await params
Verification
After implementing these changes, your Next.js build should be completed successfully. You should see output similar to:
Command line
> next build
â² Next.js 15.0.3
- Environments: .env
Creating an optimized production build ...
â Compiled successfully
â Linting and checking validity of types
â Collecting page data
â Generating static pages (11/11)
â Collecting build traces
â Finalizing page optimization
Route (app) Size First Load JS
â â / 174 B 109 kB
â â /_not-found 897 B 101 kB
â â /admin 1.26 kB 101 kB
â Æ /api/articles 142 B 100 kB
â Æ /api/articles/[slug] 142 B 100 kB
â Æ /api/regenerate 142 B 100 kB
â â /articles/[slug] 174 B 109 kB
â /articles/created-from-my-phone
â /articles/generated-without-vs-code
â /articles/article-two
â /articles/article-one
+ First Load JS shared by all 99.9 kB
â chunks/0759e794-56e8ed065b5f0a78.js 52.5 kB
â chunks/743-7bb82a2990e2d984.js 45.6 kB
â other shared chunks (total) 1.88 kB
â (Static) prerendered as static content
â (SSG) prerendered as static HTML (uses generateStaticParams)
Æ (Dynamic) server-rendered on demand
dan@Dans-MacBook-Pro incremental-regeneration %
Additional Notes
- This change affects all dynamic API routes in Next.js 15
- The Promise typing allows for better handling of asynchronous route parameter resolution
- Make sure to handle Promise rejection cases in your error handling properly
- This approach works with both single and multiple dynamic segments
By following this updated typing pattern, you'll resolve the export type error and ensure your dynamic API routes work correctly in Next.js 15.