Description
Do you want to request a feature or report a bug?
Bug?
What is the current behavior?
In the definitions file, the interface for Middleware is:
interface Dispatch<S> {
<A extends Action>(action: A): A;
}
export interface MiddlewareAPI<S> {
dispatch: Dispatch<S>;
getState(): S;
}
interface Middleware {
<S>(api: MiddlewareAPI<S>): (next: Dispatch<S>) => Dispatch<S>;
}
Since the final function in the middleware thunk is typed as Dispatch<S>
, it is required to synchronously return an A
action. However, custom middleware should support other behaviors. In the definitions file:
* Middleware wraps the base dispatch function. It allows the dispatch
* function to handle async actions in addition to actions. Middleware may
* transform, delay, ignore, or otherwise interpret actions or async actions
* before passing them to the next middleware.
If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://jsfiddle.net or similar.
If I attempt to add a type to the vanillaPromise
from the middleware examples:
import { Middleware } from 'redux'
const middleware: Middleware = store => next => action => {
if (typeof action.then !== 'function') {
return next(action)
}
return Promise.resolve(action).then(store.dispatch)
}
TypeScript throws the following errors:
ERROR in [at-loader] ./src/index.tsx:23:7
TS2322: Type '<S>(store: MiddlewareAPI<S>) => (next: Dispatch<S>) => <A extends Action>(action: A) => A | Promi...' is not assignable to type 'Middleware'.
Type '(next: Dispatch<S>) => <A extends Action>(action: A) => A | Promise<A>' is not assignable to type '(next: Dispatch<S>) => Dispatch<S>'.
Type '<A extends Action>(action: A) => A | Promise<A>' is not assignable to type 'Dispatch<S>'.
Type 'A | Promise<A>' is not assignable to type 'A'.
Type 'Promise<A>' is not assignable to type 'A'.
ERROR in [at-loader] ./src/index.tsx:24:21
TS2339: Property 'then' does not exist on type 'A'.
What is the expected behavior?
I'd expect the Middleware interface to allow returning a promise-wrapped action, or void, or etc. I'm not sure the actual fix for this... Maybe something like:
export interface MiddlewareDispatch<S> {
<A extends Action>(action: Promise<A> | A): Promise<A | void> | A | void;
}
export interface MiddlewareAPI<S> {
dispatch: MiddlewareDispatch<S>;
getState(): S;
}
export interface Middleware {
<S>(api: MiddlewareAPI<S>): (next: MiddlewareDispatch<S>) => MiddlewareDispatch<S>;
}
This solves the type errors for the vanillaPromise
example, and would also solve the problems with returning void. However I'm not certain it would cover all middleware use cases.
Which versions of Redux, and which browser and OS are affected by this issue? Did this work in previous versions of Redux?
I'm using redux 3.7.2
and typescript 2.5.2
. This is the first time I've tried this.