Closed
Description
Hi. It looks like typings don't work nicely for middlewares because I can't use type of state in it, because it's type is S
(see the comment in code):
import * as redux from 'redux';
interface State {
app: {
title: string;
}
}
const initialState: State = {
app: {
title: 'awesome app',
}
}
function createMiddleware(): redux.Middleware {
return function<S>(api: redux.MiddlewareAPI<S>) {
return function (next: redux.Dispatch<S>): redux.Dispatch<S> {
return function (action) {
const state = api.getState();
// error is shown here because `app` does not exist on type `S`
console.log('app title: ', state.app.title);
next(action);
};
};
}
}
function appReducer(state: State, action) {
return state;
}
redux.createStore(
appReducer,
initialState,
redux.applyMiddleware(createMiddleware())
)
My colleague advised me to extend redux.Middleware
but then typings don't work either because following code should fail to compile, but it compiles just fine (see the comment in code):
import * as redux from 'redux';
interface State {
app: {
title: string;
}
}
export interface Middleware extends redux.Middleware {
(api: redux.MiddlewareAPI<State>): (next: redux.Dispatch<State>) => redux.Dispatch<State>;
}
function createMiddleware(): Middleware {
return function(api: redux.MiddlewareAPI<State>) {
return function (next: redux.Dispatch<State>): redux.Dispatch<State> {
return function (action) {
const state = api.getState();
// `state` is of type `State2` which doesn't have `app` property, but typescript happily compiles this
console.log('app title: ', state.app.title);
next(action);
};
};
}
}
interface State2 {
wtf: string;
}
const initialState2: State2 = {
wtf: 'ttf'
}
function appReducer(state: State2, action) {
return state;
}
redux.createStore(
appReducer,
initialState2,
redux.applyMiddleware(createMiddleware())
)
environment:
- redux: 3.7.2
- typescript: 2.6.2
so applyMiddleware
should probably take generic parameter for state and pass it to the middlewares?
// current definition
export function applyMiddleware(...middlewares: Middleware[]): GenericStoreEnhancer;
// should be probably defined something like:
export function applyMiddleware<S>(...middlewares: Middleware<S>[]): GenericStoreEnhancer;