Skip to content

Type definitions for middleware and configureStore do not propagate custom action type #4887

Description

@markboyall

We are migrating a fairly old Redux application to the latest version. However the type definitions for the current version seem to have a few issues relating to the action type. Specifically, it is sometimes simply not propagated or not available when it should be.

The first example of this is the Middleware type. next is simply defined as taking unknown when this should be our action, specifically. It's a little unclear, but perhaps next and the return value are meant to be of the Dispatch type being passed in already? This means that the "simple" code actually does not compile because the action parameter is of the wrong type.

import * as reduxToolkit from "@reduxjs/toolkit";

interface StoreState {
    test: string;
}

class Action { protected nominal: void; type: string; }
type Dispatch = reduxToolkit.Dispatch<Action>;
type Middleware = reduxToolkit.Middleware<{}, StoreState, Dispatch>;

function logAction(action: Action) {
    console.log(action);
}

export function middlewareFactory(): Middleware {
    return () => next => action => {
        logAction(action);
        return next(action);
    };
}

As an addendum, the documentation for createStore's middleware argument says that it can be a simple array of middleware, but the type definitions leave no room for this and only allows a function.

const store = reduxToolkit.configureStore<StoreState, Action>({
    preloadedState: { test: "test" },
    reducer: state => state,
    middleware: [middlewareFactory()]
});

This should compile, but does not.

Additionally, configureStore has a similar issue, except instead of supplying unknown the action parameter is set to UnknownAction even though we specifically already supply our own action type. This is because the type GetDefaultMiddleware only receives the store state, and the action type is incorrect. Therefore the following code, which should compile, does not even after explicitly stating all the relevant parameters, due to the action parameter having the wrong type.

const store = reduxToolkit.configureStore<StoreState, Action, Tuple<ReadonlyArray<Middleware>>>({
    preloadedState: { test: "test" },
    reducer: state => state,
    middleware: defaultMiddleware => defaultMiddleware().concat(
        () => next => action => {
            logAction(action);
            return next(action);
        }
    )
});

Prior Issues

I did not find any.

What is the current behavior?

Our existing codebase is using an older version of Redux using the core APIs, but they propagate the action type correctly.

Steps to Reproduce

https://codesandbox.io is offline at the moment, but see above.

What is the expected behavior?

The expected behaviour is that Redux respects my custom action type in all type definitions.

Environment Details

We are updating from Redux 4.0.5 to Redux 5.0.1/RTK 2.12.0, on Windows 11 with Typescript 6.

It kinda seems like defaulting the action type in the type definitions just means that cases where the action type is not propagated correctly are missed, and probably either it should never be defaulted or only the entry points like configureStore should be defaulted, never the types themselves.

Metadata

Metadata

Assignees

No one assigned

    Labels

    TypeScriptIssues related to TypeScript.

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions