0

I want to get the state with type checking in my redux middleware. Using Typescript 2.6.2, I can readily create a redux middleware as follows:

import { Middleware, MiddlewareAPI, Dispatch } from 'redux';
import { IState } from '~/shared/rootReducer';

const logger: Middleware = 
    <S>({ getState }: MiddlewareAPI<S>) => (next: Dispatch<S>) => (action: any) => {
    console.log(action);
    next(action);
};

export default logger;

I'd like to do const { songs } = getState(); with typechecking, but I can't infer the type of S to be of IState, which is the type of my root reducer. Attempting to do const logger: Middleware = <S extends IState> gives me this error:

Type 'S' is not assignable to type 'IState'.

I've also tried creating a method that returns state is IState, but that failed as well. And I could do this:

const state = <IState><any>getState();

But I really rather not.

1 Answer 1

4

As far as I understand TS in version redux@^3.7.2 it is not possible to have your state typed within the middleware. The following is a workaround and you need to cast the middlewares in applyMiddlewares.

Middleware

import { MiddlewareAPI, Dispatch, Action } from 'redux';
import { IState } from '~/shared/rootReducer';

const logger = (api: MiddlewareAPI<IState>) => {
  const { songs } = api.getState();
  return (next: Dispatch<IState>) => (action: Action) => {
    return next(action);
  };
};

export default logger;

logger is not of type Middleware since it's not generic over S because we closed <S> by specifying the concrete IState. applyMiddleware is expecting Middleware[] hence the cast.

Setup

applyMiddleware(...middlewares as Middleware[]);
Sign up to request clarification or add additional context in comments.

5 Comments

Doesn't work, because I get the following error in applyMiddleware(..middewares): Type 'S' is not assignable to type 'IState'.
The applyMiddleware function in their type definitions doesn't have generic typings. This is what I see in index.d.ts: export function applyMiddleware(...middlewares: Middleware[]): GenericStoreEnhancer;, which would explain the error of TS2558: Expected 0 type arguments, but got 1. that I'm getting
You're right, I checked it also. Give me a sec. I was also missing a brace };
For now you cast applyMiddleware(...middlewares as Middleware[]) and get on with it. Version 4.0 of redux has new TS definitions. I'll spend some more time on it and get back with a better solution.
The MiddlewareAPI signature has changed and should now be MiddlewareAPI<Dispatch, IState>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.