svobik7 / next-roots

Next.js utility to generate i18n routes in the new APP directory.
https://next-roots-svobik7.vercel.app/
MIT License
178 stars 12 forks source link

Fix: Resolve Argument Count Mismatch Error in generateMetadata Function Usage #219

Closed salahzsh closed 4 months ago

salahzsh commented 4 months ago

Hi svobik7, thanks for this awesome package.

Encountered an issue with generateMetadata function when trying to localize the metadata for different pages and layouts. During the build process, TypeScript throws an error due to an unexpected argument being passed to generateMetadataOrigin function.

Error:

 ✓ Compiled successfully
   Linting and checking validity of types  .Failed to compile.

./app/(routes)/(en)/get-started/page.tsx:14:33
Type error: Expected 0 arguments, but got 1.

  12 |
  13 | export async function generateMetadata(props:any) {
> 14 |   return generateMetadataOrigin({ ...props, pageHref: "/get-started" })
     |                                 ^
  15 | }
  16 |
error Command failed with exit code 1.

Added // @ts-ignore above generateMetadataOrigin to prevent this error being fired. If I'm not mistaken is the same way is/was fixed in the export of the LayoutOrigin and PageOrigin components, not sure if it's still necessary there, just removed the ts-ignore and it didn't complain but didn't want to modify it since haven't fully checked all the code and might be something I'm missing.

{/* @ts-ignore */}
return generateMetadataOrigin({ ...props, pageHref: "/get-started" })

Let me know if there's any better way to solve it. Thanks in advance.

vercel[bot] commented 4 months ago

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
next-roots-wcmb ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 6, 2024 6:50pm
svobik7 commented 4 months ago

Hi @salahzsh could you please share your page root (origin) for mentioned get-started page?

salahzsh commented 4 months ago

Here are the page.tsx and i18n.ts files

import OnboardingSection from "@/components/sections/OnboardingSection";
import NavBar from "@/components/sections/NavBar";
import { Metadata } from "next";
import { setStaticParamsLocale } from "next-international/server";
import router from "@/lib/roots-router";
import { PageProps } from "next-roots";
import { getI18n } from "@/translations";

export async function generateMetadata() {
  const t = await getI18n()
  return {
    title: t("metadata.getStarted.title"),
    description: t("metadata.getStarted.description"),
  } satisfies Metadata
}

export default function GetStartedPage(_props: any) {
  const props = _props as PageProps
  setStaticParamsLocale(router.getLocaleFromHref(props.pageHref))
  return (
    <>
      <NavBar disableMenu />
      <main className="relative">
        <OnboardingSection />
      </main>
    </>
  );
}

app/_roots/get-started/i18n.ts

module.exports.routeNames = [
    { locale: 'es', path: 'inicia-proyecto' },
    // you don't need to specify default translation as long as it match the route folder name
    // { locale: 'en', path: 'about' },
]
svobik7 commented 4 months ago

IMO the problem is that you have generateMetadata() function defined without any param. To satisfy TS without adding @ts-ignore directive you can add param like here https://github.com/svobik7/next-roots/blob/master/examples/basic/src/routes/page.tsx

Or if you do not need it just use

generateMetadata(_: GeneratePageMetadataProps<void>)
svobik7 commented 4 months ago

BTW you can omit these nextjs types checks completely by moving your _roots folder outside app folder.

salahzsh commented 4 months ago

Thanks for your answer, that change in the param type ended up fixing the error but other ts errors appeared also complaining about types but in another place and also not consistently so depends on the page adding generateMetadata(_: GeneratePageMetadataProps<void>) solves the issue and in other pages I have to set it to generateMetadata(_: any)

Example of one of the errors:

Type error: Type 'OmitWithTag<GeneratePageMetadataProps<void>, keyof PageProps, "generateMetadata">' does not satisfy the constraint '{ [x: string]: never; }'.
  Property 'pageHref' is incompatible with index signature.
    Type 'string' is not assignable to type 'never'.

  30 | // Check the arguments and return type of the generateMetadata function
  31 | if ('generateMetadata' in entry) {
> 32 |   checkFields<Diff<PageProps, FirstArg<MaybeField<TEntry, 'generateMetadata'>>, 'generateMetadata'>>()
     |               ^
  33 |   checkFields<Diff<ResolvingMetadata, SecondArg<MaybeField<TEntry, 'generateMetadata'>>, 'generateMetadata'>>()
  34 | }

Couldn't find an answer to when it works and when it doesn't since moving around pages sometimes works with the GeneratePageMetadataProps and another times I have to use any. I can create a reproduction repo if you want but moving the _roots folder outside app made it work consistently.

The previous README.md was suggesting to keep the roots folder inside app to allow RSC support but I just saw you updated the README.md and looks like it shouldn't be any problem.

I will proceed to close the PR

Thanks for your time!