reactjstypescriptasynchronousnext.js

Type error: Type '{ params: { id: string; }; }' does not satisfy the constraint 'PageProps'


I'm working on a Next.js application and trying to fetch post details based on a dynamic route parameter. However, I'm running into a TypeScript error related to params.

Error Message:

.next/types/app/(pages)/blog/[id]/edit/page.ts:34:29
Type error: Type '{ params: { id: string; }; }' does not satisfy the constraint 'PageProps'.
  Types of property 'params' are incompatible.
    Type '{ id: string; }' is missing the following properties from type 'Promise<any>': then, catch, finally, [Symbol.toStringTag]

  32 |
  33 | // Check the prop type of the entry function
> 34 | checkFields<Diff<PageProps, FirstArg<TEntry['default']>, 'default'>>()
     |                             ^
  35 |
  36 | // Check the arguments and return type of the generateMetadata function
  37 | if ('generateMetadata' in entry) {
Static worker exited with code: 1 and signal: null
 ELIFECYCLE  Command failed with exit code 1.

Code Snippet:

import { fetchUserData } from "@actions/user";
import { fetchPostDetail } from "@actions/posts";
import PostDetail from "@/components/posts/PostDetail";
import { getSession } from "@actions/auth";

async function getData(id: string, isLoggedIn: boolean) {
  try {
    const { data: post } = await fetchPostDetail(id);
    let userData = null;
    if (isLoggedIn) {
      userData = await fetchUserData();
    }
    return { post, userData };
  } catch (error: unknown) {
    return { post: null, userData: null, error };
  }
}

export default async function BlogPost({
  params,
}: {
  params: Promise<{ id: string }>;
}) {
  const id = (await params).id;

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

  const session = await getSession();
  const isLoggedIn = !!session?.userToken;
  const { post, userData, error } = await getData(id, isLoggedIn);

  if (error || !post) {
    const isServerError = error?.response?.status === 500;
    return (
      <article className="flex justify-center items-center min-h-screen">
        <div className="flex justify-center items-center w-full px-4 sm:px-6 lg:px-8">
          <div className="w-full max-w-md rounded-lg shadow-lg p-8 bg-white dark:bg-gray-800">
            <h5 className="mb-4 text-3xl font-semibold tracking-tight text-gray-900 dark:text-white text-center">
              {isServerError ? "Server Error" : "Post not found"}
            </h5>
            <p className="text-lg text-gray-600 dark:text-gray-300 text-center">
              {isServerError
                ? "There was an issue fetching the post. Please try again later."
                : "It looks like this post is not available at the moment. Please check back later or create new content."}
            </p>
          </div>
        </div>
      </article>
    );
  }

  const userId = isLoggedIn && userData?.data ? userData.data.id : "";

  return <PostDetail post={post} userId={userId} isLoggedIn={isLoggedIn} />;
}

What I've Tried

Why is params being treated as a Promise, and how can I properly type it to avoid this TypeScript error in Next.js?

EDIT: See my answer!


Solution

  • I post my answer, beacuse a I think that a lot of people are not aware that from Next.js v15 params attribute is considered as DYNAMIC API which can only be known during request - response lifecycle. That means, params needs to satisfy Promise type and to get params request for a page resource have to be made.

    Related resources:

    Async request API - next 15 breaking change

    Request response lifecycle