react-i18next: `TS2589: Type instantiation is excessively deep and possibly infinite.` with Typescript 4.5.2 and react-i18next 11.14.3

🐛 Bug Report

Using a <Trans> component with a lot of namespaces trigger the following typescript error:

TS2589: Type instantiation is excessively deep and possibly infinite.

The error starts to happen as soon as there’s more than 45 namespaces.

You can check this behavior by modifiying the following file: https://github.com/xseignard/react-i18n-ts-bug-repro/blob/main/src/i18n/locales/en/index.ts

  • export from ns0 to ns44 and there’s no errors
  • export from ns0 to ns45 (or more) and the error pops

Related issue comment: https://github.com/i18next/react-i18next/issues/1394#issuecomment-976853798

To Reproduce

Here is a repo to repro: https://github.com/xseignard/react-i18n-ts-bug-repro

git clone git@github.com:xseignard/react-i18n-ts-bug-repro.git
npm i
npm run types

Expected behavior

No typescript error

Your Environment

  • runtime version: node v14.18.1
  • typescript version: 4.5.2
  • i18next version: 21.5.3
  • react-i18next: 11.14.3
  • os: Mac

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 10
  • Comments: 25 (7 by maintainers)

Most upvoted comments

Ok, now I think I fixed it on my own repository too. Seems that my import path on the d.ts file was incorrect, but typescript was not complaining and just saying it was “any”. How embarrassing. After I fixed the path now I get what looks like proper types and error messages. I have now hundreds of those, but most are because the t function doesn’t seem to be returning a string

The typescript team improved the way recursive types work, but it seems there are still some limitations. I’ll try to find a workaround to suppress the error.

Hey guys, I didn’t manage to find a way to suppress the error, typescript team increased the number of recursive type instantiations from 50 to 100 (on TS 4.5), but it’s not enough for 45+ namespaces. The workaround (extends infer A ? A : never) that I’ve been using to suppress the error works, but only when you call a function directly, not rendering as JSX 😢 . But I have a few suggestions that should work:

1 - Call Trans function directly when useTranslation receives an array:

const { t } = useTranslation(["ns1"]);

return (
  <div className="App">
    {Trans({ t, i18nKey: "ns1:name", children: <h1>Weird</h1> })}
  </div>
);

2 - Add a ts-ignore (don’t recommend)

<div className="App">
  {/* @ts-ignore */}
  <Trans i18nKey="ns10:name" t={t}>
    <h1>Weird</h1>
  </Trans>
</div>

3 - Use patch-package, to increase the number of instances here to something like:

if (instantiationDepth === 200 || instantiationCount >= 5000000) {

You can find more info about the discussion here: https://github.com/microsoft/TypeScript/issues/34933

Experienced the same issue, the reason was similar to the one @danielo515 had. In my case, it happened due to unexported resources: image image image

Hi So we ended up relying on option 1 described in @pedrodurek’s comment

And got rid on of the annoying TS2589 error. Tested on TypeScript 4.5.5

Hello @pedrodurek , thanks for your answer.

This is my react-i18next.d.ts contents:

import 'react-i18next';
import translation from './locales/en/translation.json';
import toast from './locales/en/toasts.json';
declare module 'react-i18next' {
  interface CustomTypeOptions {
    defaultNS: 'translation';
    resources: {
      translation: typeof translation;
      toast: typeof toast;
    };
  }
}

If you have a condesandbox template I will happily try to reproduce my problem there.

Edit: Best solution is to update to version 12. It finally fixes this problem.

I found two workarounds to get rid of the error when using the useTranslation() hook. Just type the hook. Hope that helps someone.

// before
const {t} = useTranslation(['foo', 'bar'])

// workaround 1 - explicit typing
const {t} = useTranslation<['foo', 'bar']>(['foo', 'bar'])
// or
const {t} = useTranslation<('foo' | 'bar')[]>(['foo', 'bar'])


// workaround 2 - use any
const {t} = useTranslation<any>(['foo', 'bar'])

Hey @danielo515, that can also happen if there is something wrong with your configuration (react-i18next.d.ts), can you share a simplified version of your configuration on codesandbox?