在TypeScript中包装react-redux的connect函数会导致编译错误

时间:2019-01-20 14:23:34

标签: typescript react-redux

我正在尝试将react-redux的connect函数包装到测试实用程序的辅助函数中。

下面是一个简化的示例:

interface IProps {
  number: number
}

class NumberDisplay extends React.PureComponent<IProps> {
  render() {
    return `${this.props.number}`
  }
}

function mapStateToProps(state: any) {
  return {number: 1}
}

以下按预期工作:

const ConnectedNumberDisplay1 = connect(mapStateToProps)(NumberDisplay)
export const display1 = <ConnectedNumberDisplay1 />

它提供了有用的类型检查:如果从未设置number,则编译将失败。

我的自动换行功能如下:

function wrap<StateProps, ComponentProps>(
  mapStateToProps: (state: any) => StateProps,
  Component: React.ComponentType<ComponentProps>
) {
  return connect(mapStateToProps)(Component)
                               // ^^^^^^^^^ Error happens here
}

const ConnectedNumberDisplay2 = conn(mapStateToProps, NumberDisplay)
export const display2 = <ConnectedNumberDisplay2 />

这是错误:

Argument of type 'ComponentType<ComponentProps>' is not assignable to parameter of type 'ComponentType<Matching<StateProps & DispatchProp<AnyAction>, ComponentProps>>'.
  Type 'ComponentClass<ComponentProps, any>' is not assignable to type 'ComponentType<Matching<StateProps & DispatchProp<AnyAction>, ComponentProps>>'.
    Type 'ComponentClass<ComponentProps, any>' is not assignable to type 'ComponentClass<Matching<StateProps & DispatchProp<AnyAction>, ComponentProps>, any>'.
      Types of property 'propTypes' are incompatible.
        Type 'WeakValidationMap<ComponentProps> | undefined' is not assignable to type 'WeakValidationMap<Matching<StateProps & DispatchProp<AnyAction>, ComponentProps>> | undefined'.
          Type 'WeakValidationMap<ComponentProps>' is not assignable to type 'WeakValidationMap<Matching<StateProps & DispatchProp<AnyAction>, ComponentProps>>'.
            Type '(null extends ComponentProps[K] ? Validator<ComponentProps[K] | null | undefined> : undefined extends ComponentProps[K] ? Validator<ComponentProps[K] | null | undefined> : Validator<ComponentProps[K]>) | undefined' is not assignable to type '(null extends Matching<StateProps & DispatchProp<AnyAction>, ComponentProps>[K] ? Validator<Matching<StateProps & DispatchProp<AnyAction>, ComponentProps>[K] | null | undefined> : undefined extends Matching<...>[K] ? Validator<...> : Validator<...>) | undefined'.
              Type 'null extends ComponentProps[K] ? Validator<ComponentProps[K] | null | undefined> : undefined extends ComponentProps[K] ? Validator<ComponentProps[K] | null | undefined> : Validator<ComponentProps[K]>' is not assignable to type '(null extends Matching<StateProps & DispatchProp<AnyAction>, ComponentProps>[K] ? Validator<Matching<StateProps & DispatchProp<AnyAction>, ComponentProps>[K] | null | undefined> : undefined extends Matching<...>[K] ? Validator<...> : Validator<...>) | undefined'.
                Type 'Validator<ComponentProps[K] | null | undefined> | (undefined extends ComponentProps[K] ? Validator<ComponentProps[K] | null | undefined> : Validator<ComponentProps[K]>)' is not assignable to type '(null extends Matching<StateProps & DispatchProp<AnyAction>, ComponentProps>[K] ? Validator<Matching<StateProps & DispatchProp<AnyAction>, ComponentProps>[K] | null | undefined> : undefined extends Matching<...>[K] ? Validator<...> : Validator<...>) | undefined'.
                  Type 'Validator<ComponentProps[K] | null | undefined>' is not assignable to type 'null extends Matching<StateProps & DispatchProp<AnyAction>, ComponentProps>[K] ? Validator<Matching<StateProps & DispatchProp<AnyAction>, ComponentProps>[K] | null | undefined> : undefined extends Matching<...>[K] ? Validator<...> : Validator<...>'.
                    Type 'null extends ComponentProps[K] ? Validator<ComponentProps[K] | null | undefined> : undefined extends ComponentProps[K] ? Validator<ComponentProps[K] | null | undefined> : Validator<ComponentProps[K]>' is not assignable to type 'null extends Matching<StateProps & DispatchProp<AnyAction>, ComponentProps>[K] ? Validator<Matching<StateProps & DispatchProp<AnyAction>, ComponentProps>[K] | null | undefined> : undefined extends Matching<...>[K] ? Validator<...> : Validator<...>'.

作为一种临时的解决方法,我使用的是这样的东西:

function wrap<StateProps, ComponentProps>(
  mapStateToProps: (state: any) => StateProps,
  Component: React.ComponentType<ComponentProps>,
): React.ComponentType<
  Omit<ComponentProps, keyof StateProps & keyof ComponentProps>> {
  return connect(mapStateToProps)(Component as any) as any

但如果可能的话,我不希望使用any。我不确定我在这里缺少什么。任何帮助表示赞赏!

1 个答案:

答案 0 :(得分:0)

这是我现在正在使用的,使用TypeScript 3.6.3不会出现任何编译错误:

import { connect, GetProps, MapDispatchToPropsParam, Matching, ResolveThunks } from 'react-redux'

export type SelectState<GlobalState, StateSlice>
  = (state: GlobalState) => StateSlice

export function wrap<
    LocalState,
    State,
    Props,
    StateProps,
    DispatchProps,
    C extends React.ComponentType<
      Matching<StateProps & ResolveThunks<DispatchProps>, GetProps<C>>>
>(
  getLocalState: SelectState<State, LocalState>,
  mapStateToProps: (state: LocalState) => StateProps,
  mapDispatchToProps: MapDispatchToPropsParam<DispatchProps, Props>,
  Component: C,
) {
  return connect(
    (state: State) => {
      const l = getLocalState(state)
      return mapStateToProps(l)
    },
    mapDispatchToProps,
  )(Component)
}