I'm trying to learn NextJS 15, but the courses so far I'm checking are older, and therefore I am having some issues in understanding this.
In the courses basically, they can specify a type for the parameters passed to the function so that TypeScript is validating them. Usually, an interface is defined with the parameters inside.
But since NextJS 15, the parameters are async, and therefore the type is a Promise and I don't know how to make happen same validation as I see in videos.
Tutorial video code:
import React from 'react'
interface Props {
params: { slug: string[] };
searchParams: { sortOrder: string }
}
const ProductsPage({ params: {slug}, searchParams: {sortOrder} } : Props) {
return (
<>
<div>ProductsPage</div>
{slug} - {sortOrder}
</>
)
}
export default ProductsPage
My code:
import React from 'react'
interface Props {
params: { slug: string[] };
searchParams: { sortOrder: string }
}
export default async function ProductsPage({ params, searchParams }) {
const { slug } = await params;
const { sortOrder } = await searchParams;
return (
<>
<div>ProductsPage</div>
{slug} - {sortOrder}
</>
)
}
Error I get compiling:
./app/products/[[...slug]]/page.tsx:8:46
Type error: Binding element 'params' implicitly has an 'any' type.
In order to solve I tried couple of things.
export default async function ProductsPage({ params, searchParams }: Promise<Props>)
.next/types/app/products/[[...slug]]/page.ts:34:13
Type error: Type 'OmitWithTag<Promise<Props>, keyof PageProps, "default">' does not satisfy the constraint '{ [x: string]: never; }'.
Property 'then' is incompatible with index signature.
Type '<TResult1 = Props, TResult2 = never>(onfulfilled?: ((value: Props) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<...>) | null | undefined) => Promise<...>' is not assignable to type 'never'.
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) {
export default async function ProductsPage({ params, searchParams }: Props)
.next/types/app/products/[[...slug]]/page.ts:34:13
Type error: Type 'OmitWithTag<Promise<Props>, keyof PageProps, "default">' does not satisfy the constraint '{ [x: string]: never; }'.
Property 'then' is incompatible with index signature.
Type '<TResult1 = Props, TResult2 = never>(onfulfilled?: ((value: Props) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<...>) | null | undefined) => Promise<...>' is not assignable to type 'never'.
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) {
Next.js build worker exited with code: 1 and signal: null
Does any expert here know how to make it work properly in NextJS 15 having the proper type passed into the signature so that NextJS is happy?
I'm from the Java world and this is getting me crazy :)
Thank you all!
In your code, you're making the entire props into a promise rather than the params and the searchParams. You should adjust your code as follows:
import React from 'react'
interface Props {
params: Promise<{ slug: string[] }>;
searchParams: Promise<{ sortOrder: string }>
}
export default async function ProductsPage({ params, searchParams }: Props) {
const { slug } = await params;
const { sortOrder } = await searchParams;
return (
<>
<div>ProductsPage</div>
{slug} - {sortOrder}
</>
)
}
I think this should fix your Typescript error and make your code work as it should.