typescript - i18next: Ingen överlagring matchar detta anrop när man kallar på getFixedT-funktionen
Jag använder i18next-biblioteket i en TS-app (inte React) och får ett oväntat Typescript-fel.
Jag får en typfel när jag kallar på getFixedT-funktionen. Jag skickar strängar för både lng och ns, men får ändå fel som förväntar sig null.
Att reproducera
Jag har följande typdefinition i i18next.d.ts:
// i18next.d.ts
import "i18next";
import definitions from "../i18n/locales/definitions/en.json";
import errors from "../i18n/locales/errors/en.json";
const NAMESPACES = {
definitions: "definitions",
errors: "errors",
};
declare module "i18next" {
interface CustomTypeOptions {
ns: typeof NAMESPACES.errors | typeof NAMESPACES.definitions;
returnNull: false;
resources: {
en: {
definitions: typeof definitions;
errors: typeof errors;
}
};
}
}
Mina resursfiler definieras av namnrymd, på följande sätt:
// src/i18n/locales/resources.ts
import definitions_de from './definitions/de.json';
import definitions_en from './definitions/en.json';
import errors_de from './errors/de.json';
import errors_en from './errors/en.json';
export const resources = {
de: {
definitions: definitions_de,
errors: errors_de,
},
en: {
definitions: definitions_en,
errors: errors_en,
},
// <etc>
}
Jag initierar i18nInstance och exporterar det här:
// src/i18n/index.ts
import i18n, { createInstance, InitOptions } from 'i18next';
import { fallbackLng, NAMESPACES } from '../constants';
import { resources } from './locales/resources';
const i18nInstance = createInstance();
void i18nInstance
.init({
fallbackLng, // use en if detected language is not available
defaultNS: NAMESPACES.errors,
resources,
load: 'currentOnly', // only load the detected language
ns: [NAMESPACES.definitions, NAMESPACES.errors], // namespaces
saveMissing: true, // send not translated keys to endpoint
returnNull: false,
} as InitOptions);
export default i18nInstance;
I min kod anropar jag funktionen getFixedT på följande sätt:
const locale = "en";
const t = i18nInstance.getFixedT(locale, NAMESPACES.errors)
t("path.to.definition", { variable: "value" });
Jag får följande ts-fel:
No overload matches this call.
Overload 1 of 2, '(lng: null, ns: Namespace<"en"> | null, keyPrefix?: KeyPrefix<Namespace<"en">>): TFunction<Namespace<"en">, KeyPrefix<Namespace<"en">>, Namespace<...>>', gave the following error.
Argument of type 'Locale' is not assignable to parameter of type 'null'.
Type '"de"' is not assignable to type 'null'.
Overload 2 of 2, '(lng: string | readonly string[], ns?: Namespace<"en"> | null | undefined, keyPrefix?: undefined): TFunction<Namespace<"en">, undefined, Namespace<"en">>', gave the following error.
Argument of type 'string' is not assignable to parameter of type 'Namespace<"en"> | null | undefined'.ts(2769)
- i18next version: ^22.4.9
- OS: Mac
Svar #1
Jag kunde återskapa ditt problem och hittade 2 problem, samt en lösning 🙃
Namespace<"en"> | null | undefined
Först, enligt https://www.i18next.com/overview/typescript, bör resources endast innehålla namnområdena (utan att omsluta dem i språk kod). Till exempel kan du använda din resources.ts, och göra:
declare module "i18next" {
interface CustomTypeOptions {
// I removed `ns`, as it is not supported in i18n
returnNull: false;
resources: typeof resources['en']; // equivalent of typeof { definitions: {...}, errors: {...} }
}
}
Efter ovanstående ändring fick jag detta fel:
Argument av typen 'sträng' kan inte tilldelas parametern av typen ''Namespace<"definitioner" | "fel"> | null | odefinierad'.ts(2769)
Återstående problem är att TypeScript inte kan härleda typen på dina namnrymdsnycklar (varje nyckel behandlades som en vanlig sträng, istället för ett bokstavligt värde). Vi kan fixa det med as const:
// As const
export const NAMESPACES = {
definitions: "definitions",
errors: "errors",
} as const;
