如何使用与调度类型不同的返回类型键入Redux调度程序



我想用与调度类型不同类型的动作创建者。

我试图用两种类型键入Thunkult,但这不是理想的。

// types.ts
interface AppListAction extends FetchAction {
  type: typeof APP_LIST,
  [FETCH]: {},
}
interface AppListSuccessAction extends FetchResponseAction {
  type: typeof APP_LIST_SUCCESS,
  response: Array<ListModel>
}
export type AppResponseActions =
  AppListSuccessAction
export type AppActions =
  AppListAction
  | AppResponseActions

// actions.ts
export const loadListCreator = (): AppActions => ({
  type: C_LIST,
  [FETCH]: {},
})
export const loadList = (): ThunkResult<AppResponseActions> => (dispatch: ThunkDispatcher) => dispatch(loadListCreator())

我期望没有错误,而是收到:

打字稿错误:键入'appactions'不能分配给"批准"。 类型"应用程序"不能分配给"批准"。 类型为" Applistaction"中缺少属性"响应",但类型为" Applistuccessaction"中需要。TS2322

使您的代码可编译我按照假设

进行编译
import { ThunkAction, ThunkDispatch } from 'redux-thunk';
const FETCH = 'fetch';
interface FetchAction {
    [FETCH]: object;
}
interface FetchResponseAction {
    prop2: string;
}
const APP_LIST = 'APP_LIST';
const APP_LIST_SUCCESS = 'APP_LIST_SUCCESS';
interface ListModel {
    prop3: string;
}

和您的代码之后

type ThunkResult<R> = ThunkAction<R, State, undefined, AppActions>;
type ThunkDispatcher = ThunkDispatch<State, undefined, AppActions>;

在您的代码上方的假设中给定的假设可以通过以下修改

进行编译
export const loadList = (): ThunkResult<AppActions> => (dispatch: ThunkDispatcher) => dispatch(loadListCreator());

ThunkResult<AppActions>应该具有R = AppActions的类型。RThunkResult类型的函数返回值。在redux-thunk源代码中,ThunkAction定义如下

export type ThunkAction<
    TReturnType,
    TState,
    TExtraThunkArg,
    TBasicAction extends Action
> = (
    dispatch: ThunkDispatch<TState, TExtraThunkArg, TBasicAction>,
    getState: () => TState,
    extraArgument: TExtraThunkArg
) => TReturnType;

so ThunkAction(ThunkResult在其上是基于的(是返回类型TReturnType的值。

然后,您尝试使ThunkResult<>类型的loadlist等于(dispatch: ThunkDispatcher) => dispatch(loadListCreator())。从本质上讲,它也是函数,但dispatch调用的返回结果。dispatch是类型ThunkDispatcher,从源中具有类型

export interface ThunkDispatch<
    TState,
    TExtraThunkArg,
    TBasicAction extends Action
> {
    <TReturnType>(
        thunkAction: ThunkAction<TReturnType, TState, TExtraThunkArg, TBasicAction>
    ): TReturnType;
    <A extends TBasicAction>(action: A): A;
}

因此,它是用一个类型A的Agrument和类型A的返回结果的函数超载功能。由于dispatch是由loadListCreator()呼叫的结果调用的,该呼叫返回了AppActions类型的返回,因此A被推断为AppActions

原始代码未正确编译,因为您想为fucntion返回 AppActions返回函数返回 AppResponseActionsAppActions是联合类型,可以是AppResponseActionsAppListAction。如果是AppListAction,则不能分配给AppResponseActions

我认为我已经清楚地描述了: - (

从练习的角度来看,您的代码有点过于复杂。

考虑以这种方式简化它。

  1. 从动作类型继承所有动作

    import { Action } from 'redux';
    interface AppListAction extends Action {
        type: typeof APP_LIST,
        [FETCH]: {},
    }
    
  2. 将类型ThunkResult设置为以下

    type ThunkResult = ThunkAction<void, State, undefined, AppActions>;
    

    很可能您不需要TReturnType。thunk Action只需派遣代码中所需的一切,然后返回什么都没有返回(void(。

  3. 同步操作的动作创建者可能看起来像

    interface SyncAction1 extends Action {
        type: 'SYNC_ACTION',
        argument: string
    }
    const SomeSyncAction = (argument: string) => <SyncAction1>{ type: 'SYNC_ACTION', argument }
    
  4. 异步动作的动作创造者看起来像

    export const loadList = (): ThunkResult => (dispatch: ThunkDispatcher) => {
         dispatch(/* start loading */);
         const result = await // load api call
         dispatch(loadListCreator(result));
    }
    
  5. 还原器看起来像

    export function loadReducer (state = initalState, action: AppActions)
    // reducer code
    

最新更新