在 Typescript 中使用高阶组件

Using higher order component in Typescript

我正在尝试将 react-i18next 与 Typescript 一起使用,但我 运行 遇到了一些问题。

这是我期待的道具界面。

import * as i18n from 'i18next';

export interface ReactI18nProps {
  t: i18n.TFunction;
}

然后我有一个导航组件,由我编写。

import { translate } from 'react-i18next';

function Navigation({ t }: ReactI18nProps) {
  const userProfile = JSON.parse(localStorage.getItem('profile') || '');
  return (
    ...
  );
}

export default translate('navigation')(Navigation);

现在我只想渲染我编写的这个组件

function Appliances({ location }: NavLinkProps) {
  const userId = location && location.state.userId;
  return (
    <div>
      <Navigation />
    </div>
  );
}

然而,在这个时候,TS 失败了,我得到了以下错误

Type '{}' is not assignable to type 'IntrinsicAttributes & ReactI18nProps'.
  Type '{}' is not assignable to type 'ReactI18nProps'.
    Property 't' is missing in type '{}'.

谁能解释一下我做错了什么。

如错误信息所示:

Property 't' is missing in type '{}'

您的组件期望道具为:

interface ReactI18nProps {
    t: i18n.TFunction;
}

但是你没有通过这个 t:

<Navigation />

您可以将此 t 属性 设为可选:

interface ReactI18nProps {
    t?: i18n.TFunction;
}

或满足:

<Navigation t={ (key: string, options: i18n.TOptions) => return getTranslation(key, options) } />

编辑

基于 react-i18next translation function 的类型定义:

function translate<TKey extends string = string>
    (namespaces?: TKey[] | TKey, options?: TOptions)
        : <C extends Function>(WrappedComponent: C) => C;

您传递的组件类型与您返回的类型完全相同,这意味着使用了相同的道具类型。
在这种情况下,您需要使用可选的 t,因为有时它会在没有 属性 的情况下使用(当您调用它时),但随后它会与 t 一起使用(当 translate 方法调用它)。

为了避免编译器抱怨 t 可能未定义,您可以使用 non-null assertion operator:

function Navigation({ t }: ReactI18nProps) {
    ...
    const translation = t!(...);
    ...
}

请注意它使用的是 t! 而不是 t.