i18next / react-i18next

Internationalization for react done right. Using the i18next i18n ecosystem.
https://react.i18next.com
MIT License
9.18k stars 1.02k forks source link

react-i18next <Trans /> component values are not type safe #1772

Open samuelpucat opened 1 month ago

samuelpucat commented 1 month ago

🐛 Bug Report

When using react-i18next <Trans /> component, prop values provides no intellisense and throws no TS errors.

To Reproduce

I followed these tutorials:

  1. I generated /src/@types/resources.d.ts with i18next-resources-for-ts interface -i ./public/locales/en -o ./src/@types/resources.d.ts script:
// resources.d.ts

interface Resources {
  "translation": {
    ...
    "title": "Title: <strong>{{appName}}</strong>",
    ...
  },
  ...
}
export default Resources;
  1. I created /src/@types/i18next.d.ts:
// i18next.d.ts

import Resources from './resources'

declare module 'i18next' {
    interface CustomTypeOptions {
        defaultNS: 'translation';
        resources: Resources;
        allowObjectInHTMLChildren: true;
    }
}
  1. I added /public/locales/en/translation.json
{
    "title": "Title: <strong>{{appName}}</strong>"
}
  1. I used the translation like this:
<Trans
  t={t}
  i18nKey="title"
  values={{
    appName: 'Super duper app',
    // wrong value key but no TS error
    // apName: 'Super duper app',
  }}
/>

or this:

<Trans
  t={t}
  i18nKey="title"
>
  {/* wrong value key but no TS error */}
  Title <strong>{{apName: 'Super duper app'}}</strong>
</Trans>

i18nKey had good intellisense and threw TS error when I typed a different key but wrong values key didn't throw any error.

Expected behavior

I would expect same error as when using t function with wrong value keys:

{/* wrong value key with correct TS error */}
{t('title', { apName: appName })}

throws error:

Argument of type '["title", { apName: "Super duper app"; }]' is not assignable to parameter of type '[key: "title" | "title"[], options?: ({ readonly apName: "Super duper app"; } & { appName: unknown; }) | undefined] | [key: string | string[], options: { readonly apName: "Super duper app"; } & $Dictionary & { ...; }] | [key: ...]'.
  Type '["title", { apName: "Super duper app"; }]' is not assignable to type '[key: string | string[], defaultValue: string, options?: ({ readonly apName: "Super duper app"; } & $Dictionary) | undefined]'.
    Type at position 1 in source is not compatible with type at position 1 in target.
      Type '{ apName: "Super duper app"; }' is not assignable to type 'string'.

Your Environment

Thanks

P.S.: If this issue belongs to react-i18next package, please let me know and I'll move it there.

adrai commented 1 month ago

Yes, this belongs to react-i18next, but to just answer you here... the types are safe, since it checks for the i18nKey to exist...

image
marcalexiei commented 1 month ago

If anyone has time, feel free to open a PR to address this issue