Links

TypeScript

We recently moved all type enhancements described here to i18next, so if you are relying on [email protected] and [email protected], please ignore this section and follow the instructions here.
react-i18next has embedded type definitions. If your project is relying on TypeScript 4.1+, and you want to enhance IDE Experience and prevent errors (such as type coercion), you should follow the instructions below in order to get the t function fully-type safe (keys and return type).
This is an optional feature and was newly added in [email protected] Here you can see some examples of use.

Create a declaration file

TypeScript definitions for react-i18next can be extended by using Type Augmentation and Merging Interfaces. So the first step is creating a declaration file (react-i18next.d.ts), for example:
// import the original type declarations
import 'react-i18next';
// import all namespaces (for the default language, only)
import ns1 from 'locales/en/ns1.json';
import ns2 from 'locales/en/ns2.json';
// react-i18next versions lower than 11.11.0
declare module 'react-i18next' {
// and extend them!
interface Resources {
ns1: typeof ns1;
ns2: typeof ns2;
}
}
// react-i18next versions higher than 11.11.0
declare module 'react-i18next' {
// and extend them!
interface CustomTypeOptions {
// custom namespace type if you changed it
defaultNS: 'ns1';
// custom resources type
resources: {
ns1: typeof ns1;
ns2: typeof ns2;
};
};
};
Or, if you want to include all namespaces at once, you can use the following approach:
i18n.ts
export const defaultNS = 'ns1'
export const resources = {
en: {
ns1,
ns2,
},
} as const;
i18n.use(initReactI18next).init({
lng: 'en',
ns: ['ns1', 'ns2'],
defaultNS,
resources,
});
react-i18next.d.ts
import { resources, defaultNS } from './i18n';
// react-i18next versions lower than 11.11.0
declare module 'react-i18next' {
type DefaultResources = typeof resources['en'];
interface Resources extends DefaultResources {}
}
// react-i18next versions higher than 11.11.0
declare module 'react-i18next' {
interface CustomTypeOptions {
defaultNS: typeof defaultNS;
resources: typeof resources['en'];
};
};
That's all! Your t function should be fully typed by now.

Troubleshooting

Slow compilation time

In order to fully type the t function, we recursively map all nested keys from your primary locale files or objects. Depending on the number of keys your project have, the compilation time could be noticeably affected. If this is negatively influencing your productivity, this feature might not be the best choice for you. In our tests, we got great results when declaring up to 7000 keys, but it may vary according to the project size as well. If needed, you can always open an issue on Github to get some help from us.

Type errors

If you face this issue:
Argument of type 'string' is not assignable to parameter of type ...
When using the following approach (template literal with an expression):
const { t } = useTranslation();
t(`${expression}.title`);
Or:
const { t } = useTranslation(`${ns}Default`);
TypeScript will lose the literal value, and it will infer the key as string, which will cause to throw the error above. In this case, you will need to assert the template string as const, like this:
const { t } = useTranslation();
t(`${expression}.title` as const);
For now, this is the only possible workaround. This is a TypeScript limitation which will be handled on TypeScript 4.2.

Tagged Template Literal

If you are using the tagged template literal syntax for the t function, like this:
t`key1.key2`;
The keys and return type inference will not work, because TemplateStringsArray does not accept generic types yet. You can use Tagged Template Literal syntax, but it will accept any string as argument.