Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
xseignard opened this issue Nov 25, 2021 · 25 comments
Assignees

Comments

@xseignard
Copy link

xseignard commented Nov 25, 2021

馃悰 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: #1394 (comment)

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
@jamuhl
Copy link
Member

jamuhl commented Nov 25, 2021

@xseignard
Copy link
Author

xseignard commented Nov 25, 2021

I did, that's why I'm opening yet another issue on that subject.

@pedrodurek
Copy link
Member

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.

@pedrodurek
Copy link
Member

pedrodurek commented Dec 1, 2021

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: microsoft/TypeScript#34933

@danielo515
Copy link

danielo515 commented Dec 2, 2021

I don't have too many namespaces, I just have two, so where does my problem lives then?
And funnily it only happens in one part of my code. I mean, I have imported useTranslation dozen of times and just one is complaining about this problem, but it is not giving type checking either. Does it only complain the first time it finds the function being used or what.

Something to note is that my keys are deeply nested, can that be the root of the problem? They can look something like this:

t('OneOffPayItemForm.details.title.label')

@pedrodurek
Copy link
Member

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?

@danielo515
Copy link

danielo515 commented Dec 3, 2021

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.

@danielo515
Copy link

I just reproduced the issue on a codesandbox and, while trying to slim down my translation file to not expose too much information a bit I accidentally fixed it. I'll do a diff of the files to see if I can determine where the problem is

@danielo515
Copy link

danielo515 commented Dec 3, 2021

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

@xseignard
Copy link
Author

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

@danielo515
Copy link

Hello. I think I am facing again an issue related to this problem (this time for real).
Seems that our default translation namespace is too big. We just flattened it to not be too nested (and therefore don't require any recursivity) but now the sum type seems so big that node runs out of memory while type-checking. Has anyone experienced such a problem? Do you know what is the maximum "keys" per namespace that will not break node?

@pedrodurek
Copy link
Member

Hey @danielo515, can you create a similar (as nested as yours is) example on codesanbox, so I can investigate it?

@danielo515
Copy link

Sure @pedrodurek , do you have any template?

@pedrodurek
Copy link
Member

@danielo515
Copy link

I already started one, but thank you very much

@danielo515
Copy link

danielo515 commented Mar 28, 2022

Here you have a sandbox. It is only complaining about the excessively deep problem, but if you try to run type-check locally it will blow up node:
https://codesandbox.io/s/typescript-i18next-heap-issue-forked-295plm?file=/src/i18n/locales/en/ns_0.json

@laneschmidt
Copy link

@danielo515 same issue here, subscribing

@sekoyo
Copy link

sekoyo commented Jul 7, 2022

I use useTranslation in 100s of places exactly like this, and I just get this error in one file (also running TSC in the CLI) :/

Screenshot 2022-07-07 at 18 13 04

@tiavina-mika
Copy link

tiavina-mika commented Jul 11, 2022

Hello.
in react-i18next.d , I have just changed type resources: typeof resources[DEFAULT_LANGUAGE]; to resources: typeof resources.en;
here is the working react-i18next.d:

import { defaultNS, resources } from '@config/i18n/resources';
import { DEFAULT_LANGUAGE } from '@utils/constants';

// react-i18next versions higher than 11.11.0
declare module 'react-i18next' {
  interface CustomTypeOptions {
    defaultNS: typeof defaultNS;
    resources: typeof resources.en;
  };
};

@the-night-wing
Copy link

the-night-wing commented Jul 21, 2022

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

@sekoyo
Copy link

sekoyo commented Jul 21, 2022

Ah thanks @the-night-wing and @tiavina-mika I didn't set this stuff up and noticed it was resources: typeof resources['en'] but should have been resources: typeof resources['en-US'] for my use case

@mstuercke
Copy link

mstuercke commented Oct 20, 2022

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'])

@kai-dorschner-twinsity
Copy link

@mstuercke sounds like you are avoiding the types completely with your workaround. You could've just deleted the react-i18next.d.ts file entirely and have the same effect.

@mstuercke
Copy link

@kai-dorschner-twinsity You're right. I see it as a temporary fix until there is a better solution. I'm not a fan of that workaround either.

@adrai
Copy link
Member

adrai commented Oct 20, 2022

fyi: #1501

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests