0

I'm deploying a Next.js 15.3.3 app to Vercel and encountering a TypeScript error related to dynamic route parameters. The error says: "Type '{ params: { questionId: string; questionSlug: string; }; }' does not satisfy the constraint 'PageProps'. Type '{ questionId: string; questionSlug: string; }' is missing the following properties from type 'Promise': then, catch, finally..."

It seems like Next.js expects params to be a Promise, which doesn't make sense. I’m using the App Router, and my page function looks like:

export default async function Page({ params }: { params: { questionId: string; questionSlug: string } }) { ... }

I tried wrapping params in await Promise.resolve() but that didn't help either. This only occurs during the Vercel production build, not locally. How can I fix this?

I expected the params object to be directly available in the Page and Layout functions as usual in the Next.js App Router. I tried explicitly typing the function argument as { params: { questionId: string; questionSlug: string } }, and also tried wrapping params in await Promise.resolve(params) as a workaround, thinking maybe Vercel expects a resolved Promise. However, neither helped — the Vercel build still fails, saying that params is expected to be a Promise. Locally, everything works perfectly and there are no TypeScript errors during development or local production builds.

1
  • Please provide enough code so others can better understand or reproduce the problem. Commented Jun 21 at 18:39

1 Answer 1

1

When using dynamic segments in React Server Components (RSC), you need to await the params object. For example:

// invoices/[id]/page.tsx
const InvoicePage = ({ params }: { params: { id } }) => {
   console.log(params.id) // prints 1,2,3
}

Instead you need to do something like,

export default async function InvoicePage({
  params,
}: {
  params: Promise<{ id: string }> // Pay attention to the Promise<{}>
}) {
  const { id } = await params // Also notice the await 
  return <div>My Invoice: {id}</div>
}

Learn more: https://nextjs.org/docs/app/api-reference/file-conventions/dynamic-routes

Alternatively, if you’re working in a Client Component, you can use the useParams hook:

'use client'
import { useParams } from 'next/router';

const InvoicePage = () => {
   const params = useParams();
   console.log(params.id) // prints 1,2,3
}
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.