【typescript】redux-thunk中间件派发函数导致connect类型报错解决方案

场景复现

  • 由于使用redux-thunk,所以action是允许派发函数的。但是写个action函数后做成mapDispatchToProps传给组件后,connect检测类型产生报错,报错如下:
function Profile(props: React.PropsWithChildren.PoorMansUnknown> & ProfileState & {
    ...;
}>): JSX.Element
类型“(props: PropsWithChildren & ProfileState & { validate(): { type: string; payload: Promise<...>; }; logout(): (dispatch: Dispatch<...>) => void; }>) => Element”的参数不能赋给类型“ComponentType { type: string; payload: Promise>; }; logout: () => void; }, RouteComponentProps<{}, StaticContext, PoorMansUnknown> & ProfileState & { ...; }>>”的参数。
  不能将类型“(props: PropsWithChildren & ProfileState & { validate(): { type: string; payload: Promise<...>; }; logout(): (dispatch: Dispatch<...>) => void; }>) => Element”分配给类型“FunctionComponent { type: string; payload: Promise>; }; logout: () => void; }, RouteComponentProps<{}, StaticContext, PoorMansUnknown> & ProfileState & { ...; }>>”。
    参数“props”和“props” 的类型不兼容。
      不能将类型“PropsWithChildren { type: string; payload: Promise>; }; logout: () => void; }, RouteComponentProps<{}, StaticContext, PoorMansUnknown> & ProfileState & { ...; }>>”分配给类型“PropsWithChildren & ProfileState & { validate(): { type: string; payload: Promise<...>; }; logout(): (dispatch: Dispatch<...>) => void; }>”。
        不能将类型“PropsWithChildren { type: string; payload: Promise>; }; logout: () => void; }, RouteComponentProps<{}, StaticContext, PoorMansUnknown> & ProfileState & { ...; }>>”分配给类型“{ validate(): { type: string; payload: Promise>; }; logout(): (dispatch: Dispatch) => void; }”。
          The types returned by 'logout(...)' are incompatible between these types.
            不能将类型“void”分配给类型“(dispatch: Dispatch) => void”。ts(2345)

解决方法

  • 最简单方法,直接把props类型改成any。不要用自己组出来的类型。
  • 第二种方法,这个报错主要是因为connect函数的声明文件其中对于返回值处理是这么写的:
export type ResolveThunks<TDispatchProps> =
    TDispatchProps extends {
      [key: string]: any }
        ? {
     
            [C in keyof TDispatchProps]: HandleThunkActionCreator<TDispatchProps[C]>
        }
        : TDispatchProps;
export type InferThunkActionCreatorType<TActionCreator extends (...args: any[]) => any> =
    TActionCreator extends (...args: infer TParams) => (...args: any[]) => infer TReturn
        ? (...args: TParams) => TReturn
        : TActionCreator;

export type HandleThunkActionCreator<TActionCreator> =
    TActionCreator extends (...args: any[]) => any
        ? InferThunkActionCreatorType<TActionCreator>
        : TActionCreator;

  • 所以可以发现,它多给我们把函数处理掉了,那么我们要么改声明文件,要么自己修改下类型。
  • 如果修改声明文件(不建议)那么就把InferThunkActionCreatorType那段改成:
export type InferThunkActionCreatorType<TActionCreator extends (...args: any[]) => any> =
    TActionCreator extends (...args: infer TParams) => (...args: any[]) => infer TReturn
        ? (...args: TParams)=>(...args: TParams) => TReturn
        : TActionCreator;
  • 这样就不会报错了。

  • 如果自己修改类型,我们就自己造个dispatchAction类型。本来传入组件使用的类型是:

type Props = PropsWithChildren<RouteComponentProps&ReturnType<typeof mapStateToProps>&typeof mapToDispatchProps>
  • 这个mapDispatchToProps就是类似这样:
{
     
    logout(){
     
        return (dispatch:Dispatch)=>{
     
            sessionStorage.removeItem('access_token');
            dispatch(push('/login'))
        }
    },
}
  • 然后将类型提取出来,自己组装个mapDispatchToProps类型。
let profileDispatchAction={
     
    logout(){
     
        return (dispatch:Dispatch)=>{
     
            sessionStorage.removeItem('access_token');
            dispatch(push('/login'))
        }
    }
}
type mapDispatchToPropsFunction<T> ={
     
    [K in  keyof T]:(...args:any)=>void|{
     type:string,payload:any}
}
type mapDispatchToProps=mapDispatchToPropsFunction<typeof profileDispatchAction>
  • 最后把所有类型结合一下:
type Props = PropsWithChildren<
RouteComponentProps&
ReturnType<typeof mapStateToProps>&
mapDispatchToProps
>
  • 就完美啦。

你可能感兴趣的:(typescript,redux,React)