【typescript】redux-thunk中間件派發函數導致connect類型報錯解決方案

場景復現

  • 由於使用redux-thunk,所以action是允許派發函數的。但是寫個action函數後做成mapDispatchToProps傳給組件後,connect檢測類型產生報錯,報錯如下:
function Profile(props: React.PropsWithChildren<RouteComponentProps<{}, StaticContext, History<HistoryLocationState = History.PoorMansUnknown>.PoorMansUnknown> & ProfileState & {
    ...;
}>): JSX.Element
類型“(props: PropsWithChildren<RouteComponentProps<{}, StaticContext, PoorMansUnknown> & ProfileState & { validate(): { type: string; payload: Promise<...>; }; logout(): (dispatch: Dispatch<...>) => void; }>) => Element”的參數不能賦給類型“ComponentType<Matching<ProfileState & { validate: () => { type: string; payload: Promise<AxiosResponse<any>>; }; logout: () => void; }, RouteComponentProps<{}, StaticContext, PoorMansUnknown> & ProfileState & { ...; }>>”的參數。
  不能將類型“(props: PropsWithChildren<RouteComponentProps<{}, StaticContext, PoorMansUnknown> & ProfileState & { validate(): { type: string; payload: Promise<...>; }; logout(): (dispatch: Dispatch<...>) => void; }>) => Element”分配給類型“FunctionComponent<Matching<ProfileState & { validate: () => { type: string; payload: Promise<AxiosResponse<any>>; }; logout: () => void; }, RouteComponentProps<{}, StaticContext, PoorMansUnknown> & ProfileState & { ...; }>>”。
    參數“props”和“props” 的類型不兼容。
      不能將類型“PropsWithChildren<Matching<ProfileState & { validate: () => { type: string; payload: Promise<AxiosResponse<any>>; }; logout: () => void; }, RouteComponentProps<{}, StaticContext, PoorMansUnknown> & ProfileState & { ...; }>>”分配給類型“PropsWithChildren<RouteComponentProps<{}, StaticContext, PoorMansUnknown> & ProfileState & { validate(): { type: string; payload: Promise<...>; }; logout(): (dispatch: Dispatch<...>) => void; }>”。
        不能將類型“PropsWithChildren<Matching<ProfileState & { validate: () => { type: string; payload: Promise<AxiosResponse<any>>; }; logout: () => void; }, RouteComponentProps<{}, StaticContext, PoorMansUnknown> & ProfileState & { ...; }>>”分配給類型“{ validate(): { type: string; payload: Promise<AxiosResponse<any>>; }; logout(): (dispatch: Dispatch<AnyAction>) => void; }”。
          The types returned by 'logout(...)' are incompatible between these types.
            不能將類型“void”分配給類型“(dispatch: Dispatch<AnyAction>) => 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>
  • 這個mapToDispatchProps就是類似這樣:
{
    logout(){
        return (dispatch:Dispatch)=>{
            sessionStorage.removeItem('access_token');
            dispatch(push('/login'))
        }
    },
}
  • 然後將類型提取出來,自己組裝個mapToDispatchProps類型。
let profileDispatchAction={
    logout(){
        return (dispatch:Dispatch)=>{
            sessionStorage.removeItem('access_token');
            dispatch(push('/login'))
        }
    }
}
type mapToDispatchPropsFunction<T> ={
    [K in  keyof T]:()=>void|{type:string,payload:any}
}
type mapToDispatchProps=mapToDispatchPropsFunction<typeof profileDispatchAction>
  • 最後把所有類型結合一下:
type Props = PropsWithChildren<
RouteComponentProps&
ReturnType<typeof mapStateToProps>&
mapToDispatchProps
>
  • 就完美啦。
發佈了153 篇原創文章 · 獲贊 8 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章