我在 TS 应用程序(不是 React)中使用 i18next 库并收到意外的 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)
我能够重现您的问题并发现 2 个问题和一个解决方案 🙃
命名空间<"en"> |空 |未定义
首先,根据 https://www.i18next.com/overview/typescript,
resources
应该只包含名称空间(不将它们包装在语言代码中)。例如,您可以使用您的resources.ts
,并执行:
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: {...} }
}
}
经过上述更改后,我得到了这个错误:
“字符串”类型的参数不可分配给“`命名空间”类型的参数<"definitions" | "errors"> |空 |未定义'.ts(2769)
剩下的问题是 TypeScript 无法推断您的命名空间键的类型(每个键都被视为纯字符串,而不是文字值)。我们可以用
as const
解决这个问题:
// As const
export const NAMESPACES = {
definitions: "definitions",
errors: "errors",
} as const;