英文:
i18next: No overload matches this call when calling getFixedT function
问题
我在TS应用程序中使用i18next库(不是React),并遇到了一个意外的Typescript错误。
在调用getFixedT
函数时,出现了类型不匹配的错误。我为lng
和ns
都传递了字符串,但却收到期望null
的错误。
复现步骤
我在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;
}
};
}
}
我的资源文件按命名空间定义,如下:
// 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>
}
我在此处初始化i18nInstance
并导出它:
// 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;
在我的代码中,我调用getFixedT
函数如下:
const locale = "en";
const t = i18nInstance.getFixedT(locale, NAMESPACES.errors)
t("path.to.definition", { variable: "value" });
我收到以下ts错误:
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版本: ^22.4.9
- 操作系统: Mac
英文:
I'm using the i18next library in a TS app (not React) and getting an unexpected Typescript error.
I'm getting a type mismatch when calling the getFixedT
function. I'm passing strings for both lng
and ns
, yet getting errors expecting null
.
To Reproduce
I have the following type definition in 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;
}
};
}
}
My resource files are defined by namespace, like so:
// 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>
}
I init i18nInstance
and export it here:
// 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;
In my code, I'm calling the getFixedT
function likes so:
const locale = "en";
const t = i18nInstance.getFixedT(locale, NAMESPACES.errors)
t("path.to.definition", { variable: "value" });
I get the following ts error:
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
答案1
得分: 2
我能够重现您的问题,并找到了2个问题以及一个解决方案 😊
首先,根据https://www.i18next.com/overview/typescript的说法,resources
应该只包含命名空间(不包裹在语言代码中)。例如,您可以使用您的resources.ts
,并进行以下更改:
declare module "i18next" {
interface CustomTypeOptions {
// 我移除了 `ns`,因为它在 i18n 中不受支持
returnNull: false;
resources: typeof resources['en']; // 等同于 typeof { definitions: {...}, errors: {...} }
}
}
在进行上述更改后,我得到了这个错误:
参数的类型 'string' 不能赋值给类型 'Namespace<"definitions" | "errors"> | null | undefined'.ts(2769)
剩下的问题是TypeScript不能推断出您的命名空间键的类型(每个键都被视为普通字符串,而不是字面值)。我们可以通过as const
修复这个问题:
// 使用 as const
export const NAMESPACES = {
definitions: "definitions",
errors: "errors",
} as const;
英文:
I was able to reproduce your issue and found 2 problems, and a solution 🙃
> Namespace<"en"> | null | undefined
First, according to https://www.i18next.com/overview/typescript, resources
should contain just the namespaces (without wrapping them in language code). For example, you can use your resources.ts
, and do:
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: {...} }
}
}
After above change, I got this error:
> Argument of type 'string' is not assignable to parameter of type '`Namespace<"definitions" | "errors"> | null | undefined'.ts(2769)
Remaining problem is that TypeScript can not infer the type of your namespace keys (each key was treated as a plain string, instead of a literal value). We can fix that with as const
:
// As const
export const NAMESPACES = {
definitions: "definitions",
errors: "errors",
} as const;
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论