It is a bug
I have this simple middleware:
import { Middleware, Store, Dispatch, Action } from 'redux';
import { AppState } from 'types/appState';
export default function createSimpleMiddleware(): Middleware {
return (store: Store<AppState>) => (next: Dispatch<AppState>) => (action: Action): Action => {
return next(action);
};
}
It is useless, but there is a problem) This code works with typescript version 2.3.x and below. But in typescript 2.4 there is an Error.
What is the current behavior?
In typescript I have this Error:
Types of parameters 'store' and 'api' are incompatible.
Type 'MiddlewareAPI<S>' is not assignable to type 'Store<AppState>'.
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.
You can find demo code at the top of current issue.
What is the expected behavior?
I expect, that there won't be any errors.
Which versions of Redux, and which browser and OS are affected by this issue? Did this work in previous versions of Redux?
Typescript: 2.4.1
Redux: 3.7.1
NodeJS: 6.9.1
OS: MacOS
Just merged this in yesterday: #2467
@timdorr but my bug is not about reducers. It is about middleware) Fix from #2467 fixes many problems, yes, but not for middleware.
Sorry, this is all sort of a mess and I'm not well-versed in TS. Is #2483 related?
@artem-malko could you test this pr #2479 with [email protected], it works well in my project.
@timdorr I understand. No #2483 is about reducers too, not about middleware)
@morlay no, my example is not working(
Types of parameters 'store' and 'api' are incompatible.
Type 'MiddlewareAPI<S>' is not assignable to type 'Store<AppState>'.
And if I change code to:
import { Middleware, MiddlewareAPI, Dispatch, Action } from 'redux';
import { AppState } from 'types/appState';
export default function createSimpleMiddleware(): Middleware {
return (store: MiddlewareAPI<AppState>) => (next: Dispatch<AppState>) => (action: Action): Action => {
return next(action);
};
}
It has errors too:
ypes of parameters 'store' and 'api' are incompatible.
Type 'MiddlewareAPI<S>' is not assignable to type 'MiddlewareAPI<AppState>'.
Type 'S' is not assignable to type 'AppState'.
@timdorr @morlay hey, any updates?)
@artem-malko after [email protected] change the generics check,
Middleware should change the position ofS too.
export interface Middleware<S> {
(api: MiddlewareAPI<S>): (next: Dispatch<S>) => Dispatch<S>;
}
Middleware should change the position of
Stoo.
Most middlewares can work regardless of state type, so in these cases, it's not a type parameter of Middleware, but of its call signature.
As you can see in typings for Store enhancers, there are two versions: one for fixed state type, and one generic. I think we should follow the same approach for middleware.
@morlay @aikoven yes, I have just copied all types for redux and made as @morlay said. And it works.
I have the same problem and don't really know how to overcome this without forcing an <any> and then cast back to <State>. That's a dirty cheat and I don't like it.
My function is as small as this: http://i.imgur.com/qcxGmoj.gifv
What should I do to fix this? I don't understand half of the messages above, sorry :-/
My typescript version is 2.5.0-dev.20170712. The same happens with 2.4.1
I have reducers correctly typed, as you can see createStore returns my State type.
@Llorx What error do you get?
@aikoven Ok, this is weird. I had a method that accepted a State parameter and when I do store.getState() it break saying that S cannot be converted to State, so, meanwhile, I foced an any.
Now I removed the any cast to see the error again and it works...: http://i.imgur.com/8ikVGgM.gifv
I guess that I had a type problem elsewhere that affected here. I thought that the IDE should show MiddlewareAPI<State> instead of MiddlewareAPI<S> to tell that detected the type correctly, that's why I showed the first gif, but seems that it doesn't.
I can reproduce the error:
Types of parameters 'store' and 'api' are incompatible.
Type 'MiddlewareAPI<S>' is not assignable to type 'MiddlewareAPI<IState>'.
Type 'S' is not assignable to type 'IState'.
I tried to change the typings for Middleware as @morlay suggested, but it clashed with reduxThunk.
TypeScript: 2.4.2
Redux: 3.7.2
NodeJS: 8.1.4
OS: MacOS
This is my workaround for now:
declare module 'redux' {
export interface Middleware<T=any> {
<S>(api: MiddlewareAPI<S>): (next: Dispatch<S>) => Dispatch<S>;
(api: MiddlewareAPI<T>): (next: Dispatch<T>) => Dispatch<T>;
}
}
@timdorr Shouldn't we reopen this until it is fixed?
Please reopen, this is not fixed yet. I still have the same error too
TypeScript: 2.4.2
Redux: 3.7.2
NodeJS: 7.7.3
OS: MacOS
Can someone work up a fix PR?
Should be fixed by #2563
Is it possible to add an example of what a valid middleware would look like with typescript? Even after following this thread, I'm unsure how to update my middleware so that it compiles correctly and types are satisfied.
@macdonaldr93 See the tests for Middleware types.
Most helpful comment
This is my workaround for now:
@timdorr Shouldn't we reopen this until it is fixed?