Fixing the "Types of property 'params' are incompatible" Issue in NextJS 15

JustforvanJustforvan
3 min read

NextJS is a huge framework in the web development industry in 2025. Lots of people using it for their application. Be it hobbyists, professionals, etc. One thing is for sure, when we build a dynamic web app, we will almost always encountering the use of params.

The move from previous versions to Next 15 brings some unique challenges, especially when dealing with params. As the saying goes, “Every change breaks someone’s workflow”. And today, that was exactly what happened to me 😂. Hence, I want to document it as a blog post for further reference for anyone who need it (might as well be future me imo).

TL;DR

type Params = Promise<{ slug: string }>;

The problem

Let’s say we develop a dynamic web app. Dynamic in here means we populate the app with dynamic data streams from the server (database, API, or such). As for me, I was in the middle of making two pages: blog and blog/[id]. You might have guessed that blog/[slug] needs the slug as a parameter to fetch the data from the API. My file is something like this:

blog/[slug] page:

// NOTE: I only put in the conflicting lines.
...
const PostPage = async ({ params }: { params: { slug: string } }) => {
  const post = await getPostBySlug(params.slug);

  if (!post) {
    return <div>Post not found</div>;
  }

  return (
    <>
      <Layout>
        <div className="container mx-auto px-4 max-w-3xl">
...

and while this does work locally, it went full alarm once I pushed it to Vercel. The error was

Failed to compile.
app/blog/[slug]/page.tsx
Type error: Type '{ params: { slug: string; }; }' does not satisfy the constraint 'PageProps'.
  Types of property 'params' are incompatible.
    Type '{ slug: string; }' is missing the following properties from type 'Promise<any>': then, catch, finally, [Symbol.toStringTag]

First trial

After reading the error, I then trying to do something like this

// NOTE: I only put in the conflicting lines.
...
type PageProps = {
  params: {
    slug: string;
  };
};

const PostPage = async ({ params }: PageProps) => {
  const post = await getPostBySlug(params.slug);

 if (!post) {
    return <div>Post not found</div>;
  }

  return (
    <>
      <Layout>
        <div className="container mx-auto px-4 max-w-3xl">
...

as you can see, I now throw in PageProps as a type. Once again, everything works well in dev/local but then scream when pushed to Vercel. The dreaded error was still there.

The solution

Desperate times called for a Google search. With quick searches I then found this post https://github.com/vercel/next.js/discussions/71997
and within that post was this guy’s brilliant idea (shout out to ignatiosdev):

Intrigued by his idea, I then try this

...
type Params = Promise<{ slug: string }>;

const PostPage = async ({ params }: { params: Params }) => {
  const { slug } = await params;
  const post = await getPostBySlug(slug);

  if (!post) {
    return <div>Post not found</div>;
  }

  return (
    <>
      <Layout>
        <div className="container mx-auto px-4 max-w-3xl">
...

aaand it works!
Now it works both in local and production env and nothing was broken no more. All needed to be done was adding type Params = Promise<{ slug: string }>; before calling the params as an argument to the async function.

Conclusion

Initiate Params as a type Promise and only then you can call it to the async function. For further reference, I do suggest reading the NextJS documentation. But for now, that did the job for me so I will leave it there.

Hope this helps!
Let's have further discussion in the comment and bye for now 👋👋

0
Subscribe to my newsletter

Read articles from Justforvan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Justforvan
Justforvan