Как отправить действие или ThunkAction (в TypeScript, с redux-thunk)?

скажем, у меня есть такой код:

import { Action, Dispatch } from 'redux';
import { ThunkAction } from 'redux-thunk';

interface StateTree {
  field: string;
}

function myFunc(action: Action | ThunkAction<void, StateTree, void>,
                dispatch: Dispatch<StateTree>) {
  dispatch(action); // <-- This is where the error comes from
}

...Я получаю эту ошибку от компилятора TypeScript:

ERROR in myFile.ts:x:y
TS2345: Argument of type 'Action | ThunkAction<void, StateTree, void>' is not assignable to parameter of type 'Action'.
  Type 'ThunkAction<void, StateTree, void>' is not assignable to type 'Action'.
  Property 'type' is missing in type 'ThunkAction<void, StateTree, void>'.

Я считаю, что проблема в том, как redux-thunk файл определения типа увеличивает redux Dispatch интерфейс и невозможность для TypeScript знать, какое определение Dispatch использовать.

есть ли способ обойти это?

3 ответов


Я думаю, вы правы в том, что, несмотря на возможность обрабатывать оба типа, typescript не может решить, какую перегрузку использовать.

Я думаю, что лучший вариант для вас-вернуться к нужному типу при вызове dispatch

function myFunc(action: Action | ThunkAction<void, StateTree, void>, 
                dispatch: Dispatch<StateTree>) {
  if (action instanceof ThunkAction<void, StateTree, void>) {
    dispatch(action as ThunkAction<void, StateTree, void>);
  } else {
    dispatch(action as Action);
  }
}

Я надеюсь, что я ошибаюсь, и есть лучший способ достичь этого.


подпись ThunkAction изменена с последней версией (теперь это ThunkAction<void, Your.Store.Definition, void, AnyAction>) и если только какой-то злой двойной кастинг (action as {} as Action), более элегантный способ, который я нашел, - определить Redux dispatch как ThunkDispatch следующим образом:

import { applyMiddleware, Store, createStore, AnyAction } from 'redux';
import logger from 'redux-logger';
import thunk, { ThunkDispatch } from 'redux-thunk';

import { Redux } from '../definitions';
import rootReducer from './reducers';
import { bootstrap } from './actions';

export default function configureStore() {

    const middleware = applyMiddleware( thunk, logger );

    const store: Store<Redux.Store.Definition> = createStore(rootReducer, middleware);

    // Here the dispatch casting:
    (store.dispatch as ThunkDispatch<Redux.Store.Definition, void, AnyAction>)( bootstrap() );

    return store;

}

В случае, если кто-то еще ищет обновленные ответ! ^^


это правильные типизации:https://github.com/reduxjs/redux-thunk/blob/master/test/typescript.ts

в частности:

const store = createStore(fakeReducer, applyMiddleware(thunk as ThunkMiddleware<State, Actions>));

applyMiddleware уже переопределит отправку с помощью ThunkDispatch.