我想用与调度类型不同类型的动作创建者。
我试图用两种类型键入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
的类型。R
是ThunkResult
类型的函数返回值。在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
返回函数返回 AppResponseActions
。AppActions
是联合类型,可以是AppResponseActions
或AppListAction
。如果是AppListAction
,则不能分配给AppResponseActions
。
我认为我已经清楚地描述了: - (
从练习的角度来看,您的代码有点过于复杂。
考虑以这种方式简化它。
从动作类型继承所有动作
import { Action } from 'redux'; interface AppListAction extends Action { type: typeof APP_LIST, [FETCH]: {}, }
将类型
ThunkResult
设置为以下type ThunkResult = ThunkAction<void, State, undefined, AppActions>;
很可能您不需要
TReturnType
。thunk Action只需派遣代码中所需的一切,然后返回什么都没有返回(void
(。同步操作的动作创建者可能看起来像
interface SyncAction1 extends Action { type: 'SYNC_ACTION', argument: string } const SomeSyncAction = (argument: string) => <SyncAction1>{ type: 'SYNC_ACTION', argument }
异步动作的动作创造者看起来像
export const loadList = (): ThunkResult => (dispatch: ThunkDispatcher) => { dispatch(/* start loading */); const result = await // load api call dispatch(loadListCreator(result)); }
还原器看起来像
export function loadReducer (state = initalState, action: AppActions) // reducer code