React重新构成道具上的打字稿错误

时间:2018-07-31 03:38:25

标签: reactjs typescript recompose

我有一个非常基本的有状态组件,在其中我使用recompose将多个HOC添加到我的组件中(在我的示例中,为简单起见,我仅使用一个)。由于某种原因,打字稿给我有关我的道具进入组件的错误。如何摆脱这个错误?

这是我的代码:

import * as React from 'react';
import { connect } from 'react-redux';
import { compose } from 'recompose';

interface IStoreState {
  readonly sessionState: {
    authUser: { email: string; }
  }
}

interface IAccountPageProps { 
  authUser: { email: string } 
}

const AccountPage = ({ authUser }: IAccountPageProps ) =>
    <div>
      <h1>Account: {authUser.email}</h1>
    </div>

const mapStateToProps = (state: IStoreState) => ({
  authUser: state.sessionState.authUser,
});

export default compose(
  connect(mapStateToProps)
)(AccountPage);

我得到的错误是:

Argument of type '({ authUser }: IAccountPageProps) => Element' is not assignable to parameter of type 'ComponentType<{}>'.
  Type '({ authUser }: IAccountPageProps) => Element' is not assignable to type 'StatelessComponent<{}>'.
    Types of parameters '__0' and 'props' are incompatible.
      Type '{ children?: ReactNode; }' is not assignable to type 'IAccountPageProps'.
        Property 'authUser' is missing in type '{ children?: ReactNode; }'.

如果我不使用recompose而是写

export default connect(mapStateToProps)(AccountPage)

我没有任何错误。

3 个答案:

答案 0 :(得分:6)

The current typing of compose毫无用处。如果要使用compose,则必须手动指定原始组件和最终组件的props类型,并且不会检查您指定的类型是否与您传递的高阶组件列表匹配:

export default compose<IAccountPageProps, {}>(
  connect(mapStateToProps)
)(AccountPage);

我建议不要在TypeScript中使用compose

答案 1 :(得分:1)

通过compose的键入,您可以指定生成的组件的类型以及可以调用其的组件的类型,这样可以避免出现以下错误:

export default compose<IAccountPageProps, {}>(
  connect(mapStateToProps)
)(AccountPage);

不幸的是,compose不能确保类型安全或传递给它的功能的兼容性。

因此,例如,即使它显然无效,也不会产生键入错误:

export default compose<IAccountPageProps, {}>(
  connect(mapStateToProps),
  () => 'compose typing allows any function'
)(AccountPage);

嵌套HOC调用更安全:

export default 
connect(mapStateToProps)(
  firstHoc(
    secondHoc(
      AccountPage
    )
  )
);

答案 2 :(得分:0)

我发现的最佳解决方案是重新声明类型,以便也获得connect的类型(包括.WrappedComponent,可用于轻松测试),否则默认为React.ComponentClass<{}, any>是不正确的,并且按照上述@Matt的示例,该组件没有提供有关组件的信息。

使用您的示例,请参见:

import React, { SFC } from 'react';
import { connect, ConnectedComponentClass } from 'react-redux';

export default compose<IAccountPageProps, {}>(
  connect(mapStateToProps)
)(AccountPage) as ConnectedComponentClass<SFC<IAccountPageProps>, {}>

现在,当您在其他地方使用该组件时,返回的组件将以正确的类型作为ConnectedComponentClass<React.StatelessComponent<IAccountPageProps>, {}>输入连接包装,现在您还可以访问诸如.WrappedComponent之类的connectedComponent值。

ConnectedComponentClass是react-redux的类型,因为它是所连接组件的最终类型。在理想的世界中,这不是必需的,但它可以起作用。