next.js

Type '{ id: string; }' is missing the following properties from type 'Promise<any>': then, catch, finally


I'm kinda new to using next.js. I got this error and I can't

Type error: Type 'ComposerPageProps' does not satisfy the constraint 'PageProps'. Types of property 'params' are incompatible. Type '{ id: string; }' is missing the following properties from type 'Promise': 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) {

This is my code that could cause the error:

interface ComposerPageProps {
    params: {
        id: string
    }
}

export async function generateMetadata({params}: ComposerPageProps): Promise<Metadata> {
    const composer = await getComposer(params.id)

    if (!composer) {
        return {
            title: "Composer Not Found | Sheetly",
        }
    }

    return {
        title: `${composer.name} | Composer | Sheetly`,
        description: `Explore sheet music by ${composer.name}, ${composer.periods} composer. Download and play beautiful arrangements of their most famous works.`,
    }
}

export default async function ComposerPage({params}: ComposerPageProps) {
    return (
        <ComposerPageClient id={params.id}/>
    )
}

and my client component

export default async function ComposerPageClient({id}: { id: string }) {
    const composer = await getComposer(id);
    const sheets = await getAllSheetsFromComposer(id);
    const favorites = await getFavorites();

    return (
        <div className="container mx-auto px-4 py-8">
            <ComposerProfile composer={composer} sheets={sheets}/>

            <div className="mt-12">
                <ComposerSheets sheets={sheets} userFavorites={favorites}/>
            </div>
        </div>
    )
}

Solution

  • This is an error associated with how you're defining the types for the params props in the generateMetadata function. From NextJS version 15, objects like params and searchParams passed to the page component or generateMetaData function are now Promises and not regular objects. You'll need to modify the params props from being a regular object to being a Promise. Also, you have to await the value of your params before attempting to pass it as the value to your getComposer() function.

    import type { Metadata, ResolvingMetadata } from 'next'
     
    type ComposerPageProps = {
      params: Promise<{ id: string }>
    }
    
    export async function generateMetadata({ params }: ComposerPageProps,
      parent: ResolvingMetadata): Promise<Metadata> {
        const { id } = await params;
        const composer = await getComposer(id)
    
        if (!composer) {
            return {
                title: "Composer Not Found | Sheetly",
            }
        }
    
        return {
            title: `${composer.name} | Composer | Sheetly`,
            description: `Explore sheet music by ${composer.name}, ${composer.periods} composer. Download and play beautiful arrangements of their most famous works.`,
        }
    }
    
    

    Also, based on the NextJS doc, it is recommended to use the built-in type for the generateMetadata function.

    See the docs here: https://nextjs.org/docs/app/building-your-application/optimizing/metadata#dynamic-metadata