我正在尝试使用 typescript 4.1.2 在我的 React Native 应用程序中配置react-i18next 11.8.2:
i18n.use(initReactI18next).init({
resources: {
en,
es,
},
lng: 'es',
fallbackLng: 'es',
interpolation: {
escapeValue: false,
},
});
有两个资源文件(en、es)。
但是我使用 useTranslation 挂钩在 TFunction 接口上遇到打字稿错误:
const {t, i18n} = useTranslation(['SelectLanguage']);]
<StyledLabel>{t('SelectLanguage:title')}</StyledLabel>
错误:
No overload matches this call.
Overload 1 of 2, '(props: Pick<Pick<TextProps & RefAttributes<Text>, "key" | "ref" | "style" | "onLayout" | "testID" | "nativeID" | "accessible" | "accessibilityActions" | ... 35 more ... | "dataDetectorType"> & Partial<...>, "key" | ... 42 more ... | "dataDetectorType"> & { ...; } & { ...; } & { ...; }): ReactElement<...>', gave the following error.
Type 'TFunctionResult' is not assignable to type 'string | number | TextElement | ChildElement[] | (string & {}) | (string & ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<...>)>) | ... 20 more ... | undefined'.
Type 'null' is not assignable to type 'string | number | TextElement | ChildElement[] | (string & {}) | (string & ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<...>)>) | ... 20 more ... | undefined'.
Overload 2 of 2, '(props: StyledComponentPropsWithAs<typeof Text, any, {}, never>): ReactElement<StyledComponentPropsWithAs<typeof Text, any, {}, never>, string | ... 1 more ... | (new (props: any) => Component<...>)>', gave the following error.
Type 'TFunctionResult' is not assignable to type 'string | number | TextElement | ChildElement[] | (string & {}) | (string & ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<...>)>) | ... 20 more ... | undefined'.
Type 'null' is not assignable to type 'string | number | TextElement | ChildElement[] | (string & {}) | (string & ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<...>)>) | ... 20 more ... | undefined'.ts(2769)
text.component.d.ts(15, 5): The expected type comes from property 'children' which is declared here on type 'IntrinsicAttributes & Pick<Pick<TextProps & RefAttributes<Text>, "key" | "ref" | "style" | "onLayout" | "testID" | ... 38 more ... | "dataDetectorType"> & Partial<...>, "key" | ... 42 more ... | "dataDetectorType"> & { ...; } & { ...; } & { ...; }'
text.component.d.ts(15, 5): The expected type comes from property 'children' which is declared here on type 'IntrinsicAttributes & Pick<Pick<TextProps & RefAttributes<Text>, "key" | "ref" | "style" | "onLayout" | "testID" | ... 38 more ... | "dataDetectorType"> & Partial<...>, "key" | ... 42 more ... | "dataDetectorType"> & { ...; } & { ...; } & { ...; }'
我可以通过解析 i18n 翻译的结果来解决这个错误:
<StyledLabel>{t<string>('SelectLanguage:title')}</StyledLabel>
您知道为什么会发生这种情况吗?我认为它可能是 StyledLabel 道具,它只是 @ui-kitten/components Text
的一个样式组件import styled from 'styled-components/native';
import {Text} from '@ui-kitten/components';
export const StyledLabel = styled(Text)`
margin-bottom: 5px;
`;
UI Kitten 的text.组件:
export declare class Text extends React.Component<TextProps> {
render(): React.ReactElement<RNTextProps>;
}
export {};
在错误信息中,你可以找到问题所在。
类型“TFunctionResult”不可分配给类型“string |”数量 | 文本元素 |子元素[] | (字符串&{})| (细绳 & 反应元素
TFunctionResult
仅接受字符串
解决方案:您需要始终发送一个字符串并将其引用为字符串
<StyledLabel>{t<string>('SelectLanguage:title')}</StyledLabel>
第二种解决方案
<StyledLabel>{`${t('SelectLanguage:title')}`}</StyledLabel>
创建react-i18next.d.ts
import "react-i18next";
import type * as translations from "locales";
declare module "react-i18next" {
type DefaultResources = typeof translations;
interface Resources extends DefaultResources {}
}
declare module "react-i18next" {
type Namespace = keyof typeof translations;
type Keys<N extends Namespace> = keyof typeof translations[N];
interface TFunction<
TResult extends TFunctionResult = string,
TKeys extends TFunctionKeys = string,
TInterpolationMap extends object = StringMap
> {
// basic usage
(key: TKeys | TKeys[], options?: TOptions<TInterpolationMap> | string): TResult;
// overloaded usage
(key: TKeys | TKeys[], defaultValue?: string, options?: TOptions<TInterpolationMap> | string): TResult;
}
type UseTranslationResult<N> = {
t: TFunction<string, Keys<N>>;
i18n: i18n;
ready: boolean;
};
export function useTranslation<N extends Namespace>(ns: N, options?: UseTranslationOptions): UseTranslationResult<N>;
}
就我而言,我使用的是 React 类型的 ^18 版本。如果您使用的是 React 17,请使用正确的版本:
"@types/react": "17.0.19",
"@types/react-dom": "17.0.9",
另一种解决方案是使用 withTranslation
import React from "react";
import { Link, Redirect } from "react-router-dom";
import "./Screen.css";
import ImageHolder from "../../../../assets/imageholder.png";
import { withTranslation } from "react-i18next";
export interface Screen3Props {
t: any;
}
const Screen3: React.FunctionComponent<Screen3Props> = ({ t }: Screen3Props) => {
const [redirect, setRedirect] = React.useState(false);
return (
<div className="ms-welcome initPage">
<p className="h1">{t("SEARCH_PRIMARY_TEXT")}</p>
<p className="h2">{t("SEARCH_SECONDARY_TEXT")}</p>
</div>
);
};
export default withTranslation()(Screen3);
t('SelectLanguage:title').toString() 为我解决了这个问题