Fixing Next.js 15 Dynamic Route Params Type Error
The Problem
When using dynamic routes in Next.js 15+, you might see this error:
Type error: Type '{ params: PageProps; }' does not satisfy the constraint 'PageProps'.
Types of property 'params' are incompatible.
Type 'PageParams' is missing the following properties from type 'Promise<any>': then, catch, finally, [Symbol.toStringTag]
Quick Solution
Copy this prompt and send it to your AI assistant:
I have a Next.js 15 dynamic route page ([slug]/page.tsx) with this error:
"Type 'PageParams' is missing Promise properties"
My current code:
export default async function Page({ params }: { params: { slug: string } }) {
// ... using params.slug
}
Please help me:
1. Update types to handle params as Promise
2. Fix both the page component and generateMetadata
3. Keep all existing functionality
Understanding the Issue
What Changed?
- In Next.js 15+, dynamic route parameters are now Promises
- This is different from earlier versions where they were plain objects
- This affects both page components and metadata functions
Why It Happens
- Next.js 15 made params async for better performance
- Your TypeScript types need to reflect this change
- The error occurs when types don't match Next.js's expectations
The Solution
1. Define the Params Type
type Params = Promise<{ slug: string }>
2. Update Your Page Component
export default async function Page({ params }: { params: Params }) {
const resolvedParams = await params
const slug = resolvedParams.slug
// Use slug here...
}
3. Update Metadata Function
export async function generateMetadata(
{ params }: { params: Params }
): Promise<Metadata> {
const resolvedParams = await params
const slug = resolvedParams.slug
// Use slug here...
}
Common Mistakes to Avoid
-
Forgetting to await params
// ❌ Wrong const slug = params.slug // ✅ Correct const resolvedParams = await params const slug = resolvedParams.slug -
Inconsistent type usage
// ❌ Wrong: Different types for page and metadata type PageParams = { slug: string } type MetadataParams = Promise<{ slug: string }> // ✅ Correct: Same type everywhere type Params = Promise<{ slug: string }> -
Missing Promise wrapper
// ❌ Wrong type Params = { slug: string } // ✅ Correct type Params = Promise<{ slug: string }>
When to Use This Fix
Apply this solution when:
- You're using Next.js version 15 or newer
- You have dynamic routes (pages with [brackets])
- You're getting type errors about Promise properties
- You're using TypeScript with server components
Verifying the Fix
After applying the fix:
- The type error should be gone
- Your page should still work as before
- Both metadata and page component should handle params correctly
Remember: This is specific to Next.js 15+ server components. For client components or older Next.js versions, you might need different approaches.