amannn / next-intl

🌐 Internationalization (i18n) for Next.js
https://next-intl-docs.vercel.app
MIT License
2.4k stars 217 forks source link

Localized pathname type error when reached a certain number of objects #726

Open m4rvelous252 opened 9 months ago

m4rvelous252 commented 9 months ago

Description

I'm implementing localized pathname approach with the doc when I add the language switcher that change the locale of the current page, the router.replace method would not accept the pathname variables that was returned by usePathname(). Further investigation shows it stops erroring once I reduce the number of routes in my localized pathname object, might be a typescript compiling issue 🤣 Anyway, please take a look and at the recreation repo below on the branch "next-intl-issue". If you add another route the pathname in navigation.ts typescript will error out in Switcher.tsx. In this repo the threshold is 26, but in my other project it's 24, that website has a dynamic route in the pathname.

Mandatory reproduction URL (CodeSandbox or GitHub repository)

https://github.com/m4rvelous252/next-demo/tree/next-intl-issue

Reproduction description

Steps to reproduce:

  1. Open reproduction
  2. Add an additional route to pathnames in navigation.ts
  3. See type error in Switcher.tsx

Expected behaviour

Would be nice if typescript behave correctly here

amannn commented 9 months ago

Thanks for the report! Just found this, there seems to be a limitation in TypeScript: https://github.com/microsoft/TypeScript/issues/40803. When generating a union based on a type, the number of elements is limited to 25 :-/.

You can theoretically disable type checking and allow arbitrary strings for localized pathnames like this:

export const { Link, redirect, usePathname, useRouter, getPathname } =
  createLocalizedPathnamesNavigation<typeof locales, Record<string, string>>({
    locales,
    pathnames
  });

I'd be curious if there's a better solution in case someone more experienced with TypeScript comes across this.

Any chance you could use dynamic params to reduce the number of pathnames (e.g. /product/[id])?

m4rvelous252 commented 9 months ago

Currently, I'm putting a @ts-expect-error flag above this since I'm only using it in the language switcher component, I still want to use the auto complete from next-intl (super nice btw).

  const lang = useLocale();
  const pathname = usePathname();
  const router = useRouter();
  const params = useParams();

  const handleSwitchLanguage = (lang: string) => {
    // @ts-expect-error
    router.replace({ pathname, params }, { locale: lang });
  };

Would be nice if there's another way to get around this 👍