web-dev-qa-db-fra.com

Comment envoyer une action ou une ThunkAction (sous TypeScript, avec redux-thunk)?

Disons que j'ai le code comme suit:

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
}

... Je reçois cette erreur du compilateur 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>'.

Je pense que le problème tient à la manière dont le fichier de définition de type redux-thunk augmente l'interface reduxDispatch et à l'incapacité de TypeScript de savoir quelle définition de Dispatch utiliser.

Y a-t-il un moyen de contourner ceci?

6
pleasedesktop

Je pense que vous avez raison, même si vous êtes capable de gérer les deux types, TypeScript ne peut pas déterminer quelle surcharge utiliser.

Je pense que la meilleure option pour vous est de rétablir le type souhaité lorsque vous appelez 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);
  }
}

J'espère que je me trompe et qu'il existe un meilleur moyen d'y parvenir.

2
Michael Peyper

La signature de ThunkAction a changé avec la dernière version (c'est maintenant ThunkAction<void, Your.Store.Definition, void, AnyAction>) et à moins qu'un double casting maléfique (action as {} as Action), la façon la plus élégante que j'ai trouvée est de définir l'envoi de redux comme un ThunkDispatch comme ceci:

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;

}

Si quelqu'un d'autre cherche une réponse à jour! ^^

10
pierpytom

Ce sont les typages corrects: https://github.com/reduxjs/redux-thunk/blob/master/test/TypeScript.ts

Notamment: 

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

applyMiddleware annulera déjà l'envoi avec un ThunkDispatch.

1
joaoguerravieira