Index: node_modules/@reduxjs/toolkit/src/tests/Tuple.test-d.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/Tuple.test-d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/Tuple.test-d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,83 @@
+import { Tuple } from '@reduxjs/toolkit'
+
+describe('type tests', () => {
+  test('compatibility is checked between described types', () => {
+    const stringTuple = new Tuple('')
+
+    expectTypeOf(stringTuple).toEqualTypeOf<Tuple<[string]>>()
+
+    expectTypeOf(stringTuple).toMatchTypeOf<Tuple<string[]>>()
+
+    expectTypeOf(stringTuple).not.toMatchTypeOf<Tuple<[string, string]>>()
+
+    const numberTuple = new Tuple(0, 1)
+
+    expectTypeOf(numberTuple).not.toMatchTypeOf<Tuple<string[]>>()
+  })
+
+  test('concat is inferred properly', () => {
+    const singleString = new Tuple('')
+
+    expectTypeOf(singleString).toEqualTypeOf<Tuple<[string]>>()
+
+    expectTypeOf(singleString.concat('')).toEqualTypeOf<
+      Tuple<[string, string]>
+    >()
+
+    expectTypeOf(singleString.concat([''] as const)).toMatchTypeOf<
+      Tuple<[string, string]>
+    >()
+  })
+
+  test('prepend is inferred properly', () => {
+    const singleString = new Tuple('')
+
+    expectTypeOf(singleString).toEqualTypeOf<Tuple<[string]>>()
+
+    expectTypeOf(singleString.prepend('')).toEqualTypeOf<
+      Tuple<[string, string]>
+    >()
+
+    expectTypeOf(singleString.prepend([''] as const)).toMatchTypeOf<
+      Tuple<[string, string]>
+    >()
+  })
+
+  test('push must match existing items', () => {
+    const stringTuple = new Tuple('')
+
+    expectTypeOf(stringTuple.push).toBeCallableWith('')
+
+    expectTypeOf(stringTuple.push).parameter(0).not.toBeNumber()
+  })
+
+  test('Tuples can be combined', () => {
+    const stringTuple = new Tuple('')
+
+    const numberTuple = new Tuple(0, 1)
+
+    expectTypeOf(stringTuple.concat(numberTuple)).toEqualTypeOf<
+      Tuple<[string, number, number]>
+    >()
+
+    expectTypeOf(stringTuple.prepend(numberTuple)).toEqualTypeOf<
+      Tuple<[number, number, string]>
+    >()
+
+    expectTypeOf(numberTuple.concat(stringTuple)).toEqualTypeOf<
+      Tuple<[number, number, string]>
+    >()
+
+    expectTypeOf(numberTuple.prepend(stringTuple)).toEqualTypeOf<
+      Tuple<[string, number, number]>
+    >()
+
+    expectTypeOf(stringTuple.prepend(numberTuple)).not.toMatchTypeOf<
+      Tuple<[string, number, number]>
+    >()
+
+    expectTypeOf(stringTuple.concat(numberTuple)).not.toMatchTypeOf<
+      Tuple<[number, number, string]>
+    >()
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/actionCreatorInvariantMiddleware.test.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/actionCreatorInvariantMiddleware.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/actionCreatorInvariantMiddleware.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,61 @@
+import type { ActionCreatorInvariantMiddlewareOptions } from '@internal/actionCreatorInvariantMiddleware'
+import { getMessage } from '@internal/actionCreatorInvariantMiddleware'
+import { createActionCreatorInvariantMiddleware } from '@internal/actionCreatorInvariantMiddleware'
+import type { MiddlewareAPI } from '@reduxjs/toolkit'
+import { createAction } from '@reduxjs/toolkit'
+
+describe('createActionCreatorInvariantMiddleware', () => {
+  const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
+
+  afterEach(() => {
+    consoleSpy.mockClear()
+  })
+  afterAll(() => {
+    consoleSpy.mockRestore()
+  })
+
+  const dummyAction = createAction('aSlice/anAction')
+
+  it('sends the action through the middleware chain', () => {
+    const next = vi.fn()
+    const dispatch = createActionCreatorInvariantMiddleware()(
+      {} as MiddlewareAPI,
+    )(next)
+    dispatch({ type: 'SOME_ACTION' })
+
+    expect(next).toHaveBeenCalledWith({
+      type: 'SOME_ACTION',
+    })
+  })
+
+  const makeActionTester = (
+    options?: ActionCreatorInvariantMiddlewareOptions,
+  ) =>
+    createActionCreatorInvariantMiddleware(options)({} as MiddlewareAPI)(
+      (action) => action,
+    )
+
+  it('logs a warning to console if an action creator is mistakenly dispatched', () => {
+    const testAction = makeActionTester()
+
+    testAction(dummyAction())
+
+    expect(consoleSpy).not.toHaveBeenCalled()
+
+    testAction(dummyAction)
+
+    expect(consoleSpy).toHaveBeenLastCalledWith(getMessage(dummyAction.type))
+  })
+
+  it('allows passing a custom predicate', () => {
+    let predicateCalled = false
+    const testAction = makeActionTester({
+      isActionCreator(action): action is Function {
+        predicateCalled = true
+        return false
+      },
+    })
+    testAction(dummyAction())
+    expect(predicateCalled).toBe(true)
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/autoBatchEnhancer.test.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/autoBatchEnhancer.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/autoBatchEnhancer.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,208 @@
+import { configureStore } from '../configureStore'
+import { createSlice } from '../createSlice'
+import type { AutoBatchOptions } from '../autoBatchEnhancer'
+import { autoBatchEnhancer, prepareAutoBatched } from '../autoBatchEnhancer'
+import { delay } from '../utils'
+import { debounce } from 'lodash'
+
+interface CounterState {
+  value: number
+}
+
+const counterSlice = createSlice({
+  name: 'counter',
+  initialState: { value: 0 } as CounterState,
+  reducers: {
+    incrementBatched: {
+      // Batched, low-priority
+      reducer(state) {
+        state.value += 1
+      },
+      prepare: prepareAutoBatched<void>(),
+    },
+    // Not batched, normal priority
+    decrementUnbatched(state) {
+      state.value -= 1
+    },
+  },
+})
+const { incrementBatched, decrementUnbatched } = counterSlice.actions
+
+const makeStore = (autoBatchOptions?: AutoBatchOptions) => {
+  return configureStore({
+    reducer: counterSlice.reducer,
+    enhancers: (getDefaultEnhancers) =>
+      getDefaultEnhancers({
+        autoBatch: autoBatchOptions,
+      }),
+  })
+}
+
+let store: ReturnType<typeof makeStore>
+
+let subscriptionNotifications = 0
+
+const cases: AutoBatchOptions[] = [
+  { type: 'tick' },
+  { type: 'raf' },
+  { type: 'timer', timeout: 0 },
+  { type: 'timer', timeout: 10 },
+  { type: 'timer', timeout: 20 },
+  {
+    type: 'callback',
+    queueNotification: debounce((notify: () => void) => {
+      notify()
+    }, 5),
+  },
+]
+
+describe.each(cases)('autoBatchEnhancer: %j', (autoBatchOptions) => {
+  beforeEach(() => {
+    subscriptionNotifications = 0
+    store = makeStore(autoBatchOptions)
+
+    store.subscribe(() => {
+      subscriptionNotifications++
+    })
+  })
+  test('Does not alter normal subscription notification behavior', async () => {
+    store.dispatch(decrementUnbatched())
+    expect(subscriptionNotifications).toBe(1)
+    store.dispatch(decrementUnbatched())
+    expect(subscriptionNotifications).toBe(2)
+    store.dispatch(decrementUnbatched())
+    expect(subscriptionNotifications).toBe(3)
+    store.dispatch(decrementUnbatched())
+
+    await delay(25)
+
+    expect(subscriptionNotifications).toBe(4)
+  })
+
+  test('Only notifies once if several batched actions are dispatched in a row', async () => {
+    store.dispatch(incrementBatched())
+    expect(subscriptionNotifications).toBe(0)
+    store.dispatch(incrementBatched())
+    expect(subscriptionNotifications).toBe(0)
+    store.dispatch(incrementBatched())
+    expect(subscriptionNotifications).toBe(0)
+    store.dispatch(incrementBatched())
+
+    await delay(25)
+
+    expect(subscriptionNotifications).toBe(1)
+  })
+
+  test('Notifies immediately if a non-batched action is dispatched', async () => {
+    store.dispatch(incrementBatched())
+    expect(subscriptionNotifications).toBe(0)
+    store.dispatch(incrementBatched())
+    expect(subscriptionNotifications).toBe(0)
+    store.dispatch(decrementUnbatched())
+    expect(subscriptionNotifications).toBe(1)
+    store.dispatch(incrementBatched())
+
+    await delay(25)
+
+    expect(subscriptionNotifications).toBe(2)
+  })
+
+  test('Does not notify at end of tick if last action was normal priority', async () => {
+    store.dispatch(incrementBatched())
+    expect(subscriptionNotifications).toBe(0)
+    store.dispatch(incrementBatched())
+    expect(subscriptionNotifications).toBe(0)
+    store.dispatch(decrementUnbatched())
+    expect(subscriptionNotifications).toBe(1)
+    store.dispatch(incrementBatched())
+    store.dispatch(decrementUnbatched())
+    expect(subscriptionNotifications).toBe(2)
+    store.dispatch(decrementUnbatched())
+    expect(subscriptionNotifications).toBe(3)
+
+    await delay(25)
+
+    expect(subscriptionNotifications).toBe(3)
+  })
+})
+
+describe.each(cases)(
+  'autoBatchEnhancer with fake timers: %j',
+  (autoBatchOptions) => {
+    beforeAll(() => {
+      vitest.useFakeTimers({
+        toFake: ['setTimeout', 'queueMicrotask', 'requestAnimationFrame'],
+      })
+    })
+    afterAll(() => {
+      vitest.useRealTimers()
+    })
+    beforeEach(() => {
+      subscriptionNotifications = 0
+      store = makeStore(autoBatchOptions)
+
+      store.subscribe(() => {
+        subscriptionNotifications++
+      })
+    })
+    test('Does not alter normal subscription notification behavior', () => {
+      store.dispatch(decrementUnbatched())
+      expect(subscriptionNotifications).toBe(1)
+      store.dispatch(decrementUnbatched())
+      expect(subscriptionNotifications).toBe(2)
+      store.dispatch(decrementUnbatched())
+      expect(subscriptionNotifications).toBe(3)
+      store.dispatch(decrementUnbatched())
+
+      vitest.runAllTimers()
+
+      expect(subscriptionNotifications).toBe(4)
+    })
+
+    test('Only notifies once if several batched actions are dispatched in a row', () => {
+      store.dispatch(incrementBatched())
+      expect(subscriptionNotifications).toBe(0)
+      store.dispatch(incrementBatched())
+      expect(subscriptionNotifications).toBe(0)
+      store.dispatch(incrementBatched())
+      expect(subscriptionNotifications).toBe(0)
+      store.dispatch(incrementBatched())
+
+      vitest.runAllTimers()
+
+      expect(subscriptionNotifications).toBe(1)
+    })
+
+    test('Notifies immediately if a non-batched action is dispatched', () => {
+      store.dispatch(incrementBatched())
+      expect(subscriptionNotifications).toBe(0)
+      store.dispatch(incrementBatched())
+      expect(subscriptionNotifications).toBe(0)
+      store.dispatch(decrementUnbatched())
+      expect(subscriptionNotifications).toBe(1)
+      store.dispatch(incrementBatched())
+
+      vitest.runAllTimers()
+
+      expect(subscriptionNotifications).toBe(2)
+    })
+
+    test('Does not notify at end of tick if last action was normal priority', () => {
+      store.dispatch(incrementBatched())
+      expect(subscriptionNotifications).toBe(0)
+      store.dispatch(incrementBatched())
+      expect(subscriptionNotifications).toBe(0)
+      store.dispatch(decrementUnbatched())
+      expect(subscriptionNotifications).toBe(1)
+      store.dispatch(incrementBatched())
+      store.dispatch(decrementUnbatched())
+      expect(subscriptionNotifications).toBe(2)
+      store.dispatch(decrementUnbatched())
+      expect(subscriptionNotifications).toBe(3)
+
+      vitest.runAllTimers()
+
+      expect(subscriptionNotifications).toBe(3)
+    })
+  },
+)
Index: node_modules/@reduxjs/toolkit/src/tests/combineSlices.test-d.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/combineSlices.test-d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/combineSlices.test-d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,284 @@
+import type {
+  Action,
+  Reducer,
+  Slice,
+  WithSlice,
+  WithSlicePreloadedState,
+} from '@reduxjs/toolkit'
+import { combineSlices } from '@reduxjs/toolkit'
+import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
+
+declare const stringSlice: Slice<string, {}, 'string'>
+
+declare const numberSlice: Slice<number, {}, 'number'>
+
+declare const booleanReducer: Reducer<boolean>
+
+declare const mixedReducer: Reducer<string, Action, number>
+
+declare const mixedSliceLike: {
+  reducerPath: 'mixedSlice'
+  reducer: typeof mixedReducer
+}
+
+const exampleApi = createApi({
+  baseQuery: fetchBaseQuery(),
+  endpoints: (build) => ({
+    getThing: build.query({
+      query: () => '',
+    }),
+  }),
+})
+
+type ExampleApiState = ReturnType<typeof exampleApi.reducer>
+
+describe('type tests', () => {
+  test('combineSlices correctly combines static state', () => {
+    const rootReducer = combineSlices(
+      stringSlice,
+      numberSlice,
+      exampleApi,
+      {
+        boolean: booleanReducer,
+        mixed: mixedReducer,
+      },
+      mixedSliceLike,
+    )
+
+    expectTypeOf(rootReducer(undefined, { type: '' })).toEqualTypeOf<{
+      string: string
+      number: number
+      boolean: boolean
+      api: ExampleApiState
+      mixed: string
+      mixedSlice: string
+    }>()
+
+    // test for correct preloaded state handling
+    expectTypeOf(rootReducer).toBeCallableWith(
+      { mixed: 9, mixedSlice: 9 },
+      { type: '' },
+    )
+  })
+
+  test('combineSlices allows passing no initial reducers', () => {
+    const rootReducer = combineSlices()
+
+    expectTypeOf(rootReducer(undefined, { type: '' })).toEqualTypeOf<{}>()
+
+    const declaredLazy =
+      combineSlices().withLazyLoadedSlices<WithSlice<typeof numberSlice>>()
+
+    expectTypeOf(declaredLazy(undefined, { type: '' })).toEqualTypeOf<{
+      number?: number
+    }>()
+  })
+
+  test('withLazyLoadedSlices adds partial to state', () => {
+    const rootReducer = combineSlices(stringSlice).withLazyLoadedSlices<
+      WithSlice<typeof numberSlice> & WithSlice<typeof exampleApi>
+    >()
+
+    expectTypeOf(rootReducer(undefined, { type: '' }).number).toEqualTypeOf<
+      number | undefined
+    >()
+
+    expectTypeOf(rootReducer(undefined, { type: '' }).api).toEqualTypeOf<
+      ExampleApiState | undefined
+    >()
+  })
+
+  test('inject marks injected keys as required', () => {
+    const rootReducer = combineSlices(stringSlice).withLazyLoadedSlices<
+      WithSlice<typeof numberSlice> &
+        WithSlice<typeof exampleApi> & { boolean: boolean } & WithSlice<
+          typeof mixedSliceLike
+        > &
+        WithSlice<{
+          reducerPath: 'mixedReducer'
+          reducer: typeof mixedReducer
+        }>,
+      WithSlicePreloadedState<typeof numberSlice> &
+        WithSlicePreloadedState<typeof exampleApi> & {
+          boolean: boolean
+        } & WithSlicePreloadedState<typeof mixedSliceLike> &
+        WithSlicePreloadedState<{
+          reducerPath: 'mixedReducer'
+          reducer: typeof mixedReducer
+        }>
+    >()
+
+    expectTypeOf(rootReducer(undefined, { type: '' }).number).toEqualTypeOf<
+      number | undefined
+    >()
+
+    expectTypeOf(rootReducer(undefined, { type: '' }).boolean).toEqualTypeOf<
+      boolean | undefined
+    >()
+
+    expectTypeOf(rootReducer(undefined, { type: '' }).api).toEqualTypeOf<
+      ExampleApiState | undefined
+    >()
+
+    expectTypeOf(rootReducer(undefined, { type: '' }).mixedSlice).toEqualTypeOf<
+      string | undefined
+    >()
+
+    expectTypeOf(
+      rootReducer(undefined, { type: '' }).mixedReducer,
+    ).toEqualTypeOf<string | undefined>()
+
+    const withNumber = rootReducer.inject(numberSlice)
+
+    expectTypeOf(withNumber(undefined, { type: '' }).number).toBeNumber()
+
+    const withBool = rootReducer.inject({
+      reducerPath: 'boolean' as const,
+      reducer: booleanReducer,
+    })
+
+    expectTypeOf(withBool(undefined, { type: '' }).boolean).toBeBoolean()
+
+    const withApi = rootReducer.inject(exampleApi)
+
+    expectTypeOf(
+      withApi(undefined, { type: '' }).api,
+    ).toEqualTypeOf<ExampleApiState>()
+
+    const withMixedSlice = rootReducer.inject(mixedSliceLike)
+
+    expectTypeOf(
+      withMixedSlice(undefined, { type: '' }).mixedSlice,
+    ).toBeString()
+
+    const withMixedReducer = rootReducer.inject({
+      reducerPath: 'mixedReducer',
+      reducer: mixedReducer,
+    })
+
+    expectTypeOf(
+      withMixedReducer(undefined, { type: '' }).mixedReducer,
+    ).toBeString()
+  })
+
+  test('selector() allows defining selectors with injected reducers defined', () => {
+    const rootReducer = combineSlices(stringSlice).withLazyLoadedSlices<
+      WithSlice<typeof numberSlice> & { boolean: boolean }
+    >()
+
+    type RootState = ReturnType<typeof rootReducer>
+
+    const withoutInjection = rootReducer.selector(
+      (state: RootState) => state.number,
+    )
+
+    expectTypeOf(
+      withoutInjection(rootReducer(undefined, { type: '' })),
+    ).toEqualTypeOf<number | undefined>()
+
+    const withInjection = rootReducer
+      .inject(numberSlice)
+      .selector((state) => state.number)
+
+    expectTypeOf(
+      withInjection(rootReducer(undefined, { type: '' })),
+    ).toBeNumber()
+  })
+
+  test('selector() passes arguments through', () => {
+    const rootReducer = combineSlices(stringSlice).withLazyLoadedSlices<
+      WithSlice<typeof numberSlice> & { boolean: boolean }
+    >()
+
+    const selector = rootReducer
+      .inject(numberSlice)
+      .selector((state, num: number) => state.number)
+
+    const state = rootReducer(undefined, { type: '' })
+
+    expectTypeOf(selector).toBeCallableWith(state, 0)
+
+    // required argument
+    expectTypeOf(selector).parameters.not.toMatchTypeOf([state])
+
+    // number not string
+    expectTypeOf(selector).parameters.not.toMatchTypeOf([state, ''])
+  })
+
+  test('nested calls inferred correctly', () => {
+    const innerReducer =
+      combineSlices(stringSlice).withLazyLoadedSlices<
+        WithSlice<typeof numberSlice>
+      >()
+
+    const innerSelector = innerReducer.inject(numberSlice).selector(
+      (state) => state.number,
+      (rootState: RootState) => rootState.inner,
+    )
+
+    const outerReducer = combineSlices({ inner: innerReducer })
+
+    type RootState = ReturnType<typeof outerReducer>
+
+    expectTypeOf(outerReducer(undefined, { type: '' })).toMatchTypeOf<{
+      inner: { string: string }
+    }>()
+
+    expectTypeOf(
+      innerSelector(outerReducer(undefined, { type: '' })),
+    ).toBeNumber()
+  })
+
+  test('selector errors if selectorFn and selectState are mismatched', () => {
+    const combinedReducer =
+      combineSlices(stringSlice).withLazyLoadedSlices<
+        WithSlice<typeof numberSlice>
+      >()
+
+    const outerReducer = combineSlices({ inner: combinedReducer })
+
+    type RootState = ReturnType<typeof outerReducer>
+
+    combinedReducer.selector(
+      (state) => state.number,
+      // @ts-expect-error wrong state returned
+      (rootState: RootState) => rootState.inner.number,
+    )
+
+    combinedReducer.selector(
+      (state, num: number) => state.number,
+      // @ts-expect-error wrong arguments
+      (rootState: RootState, str: string) => rootState.inner,
+    )
+
+    combinedReducer.selector(
+      (state, num: number) => state.number,
+      (rootState: RootState) => rootState.inner,
+    )
+
+    // TODO: see if there's a way of making this work
+    // probably a rare case so not the end of the world if not
+    combinedReducer.selector(
+      (state) => state.number,
+      // @ts-ignore
+      (rootState: RootState, num: number) => rootState.inner,
+    )
+  })
+
+  test('correct type of state is inferred when not declared via `withLazyLoadedSlices`', () => {
+    // Related to https://github.com/reduxjs/redux-toolkit/issues/4171
+
+    const combinedReducer = combineSlices(stringSlice)
+
+    const withNumber = combinedReducer.inject(numberSlice)
+
+    expectTypeOf(withNumber).returns.toEqualTypeOf<{
+      string: string
+      number: number
+    }>()
+
+    expectTypeOf(
+      withNumber(undefined, { type: '' }).number,
+    ).toMatchTypeOf<number>()
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/combineSlices.test.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/combineSlices.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/combineSlices.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,215 @@
+import type { WithSlice } from '@reduxjs/toolkit'
+import {
+  combineSlices,
+  createAction,
+  createReducer,
+  createSlice,
+} from '@reduxjs/toolkit'
+
+const dummyAction = createAction<void>('dummy')
+
+const stringSlice = createSlice({
+  name: 'string',
+  initialState: '',
+  reducers: {},
+})
+
+const numberSlice = createSlice({
+  name: 'number',
+  initialState: 0,
+  reducers: {},
+})
+
+const booleanReducer = createReducer(false, () => {})
+
+const counterReducer = createSlice({
+  name: 'counter',
+  initialState: () => ({ value: 0 }),
+  reducers: {},
+})
+
+// mimic - we can't use RTKQ here directly
+const api = {
+  reducerPath: 'api' as const,
+  reducer: createReducer(
+    {
+      queries: {},
+      mutations: {},
+      provided: {},
+      subscriptions: {},
+      config: {
+        reducerPath: 'api',
+        invalidationBehavior: 'delayed',
+        online: false,
+        focused: false,
+        keepUnusedDataFor: 60,
+        middlewareRegistered: false,
+        refetchOnMountOrArgChange: false,
+        refetchOnReconnect: false,
+        refetchOnFocus: false,
+      },
+    },
+    () => {},
+  ),
+}
+
+describe('combineSlices', () => {
+  it('calls combineReducers to combine static slices/reducers', () => {
+    const combinedReducer = combineSlices(
+      stringSlice,
+      {
+        num: numberSlice.reducer,
+        boolean: booleanReducer,
+      },
+      api,
+    )
+    expect(combinedReducer(undefined, dummyAction())).toEqual({
+      string: stringSlice.getInitialState(),
+      num: numberSlice.getInitialState(),
+      boolean: booleanReducer.getInitialState(),
+      api: api.reducer.getInitialState(),
+    })
+  })
+  it('allows passing no initial reducers', () => {
+    const combinedReducer = combineSlices()
+
+    const result = combinedReducer(undefined, dummyAction())
+
+    expect(result).toEqual({})
+
+    // no-op if we have no reducers yet
+    expect(combinedReducer(result, dummyAction())).toBe(result)
+  })
+  describe('injects', () => {
+    beforeEach(() => {
+      vi.stubEnv('NODE_ENV', 'development')
+
+      return vi.unstubAllEnvs
+    })
+
+    it('injects slice', () => {
+      const combinedReducer =
+        combineSlices(stringSlice).withLazyLoadedSlices<
+          WithSlice<typeof numberSlice>
+        >()
+
+      expect(combinedReducer(undefined, dummyAction()).number).toBe(undefined)
+
+      const injectedReducer = combinedReducer.inject(numberSlice)
+
+      expect(injectedReducer(undefined, dummyAction()).number).toBe(
+        numberSlice.getInitialState(),
+      )
+    })
+    it('logs error when same name is used for different reducers', () => {
+      const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
+      const combinedReducer = combineSlices(stringSlice).withLazyLoadedSlices<{
+        boolean: boolean
+      }>()
+
+      combinedReducer.inject({
+        reducerPath: 'boolean' as const,
+        reducer: booleanReducer,
+      })
+
+      combinedReducer.inject({
+        reducerPath: 'boolean' as const,
+        reducer: booleanReducer,
+      })
+
+      expect(consoleSpy).not.toHaveBeenCalled()
+
+      combinedReducer.inject({
+        reducerPath: 'boolean' as const,
+        // @ts-expect-error wrong reducer
+        reducer: stringSlice.reducer,
+      })
+
+      expect(consoleSpy).toHaveBeenCalledWith(
+        `called \`inject\` to override already-existing reducer boolean without specifying \`overrideExisting: true\``,
+      )
+      consoleSpy.mockRestore()
+    })
+    it('allows replacement of reducers if overrideExisting is true', () => {
+      const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
+      const combinedReducer = combineSlices(stringSlice).withLazyLoadedSlices<
+        WithSlice<typeof numberSlice> &
+          WithSlice<typeof api> & { boolean: boolean }
+      >()
+
+      combinedReducer.inject(numberSlice)
+
+      combinedReducer.inject(
+        { reducerPath: 'number' as const, reducer: () => 0 },
+        { overrideExisting: true },
+      )
+
+      expect(consoleSpy).not.toHaveBeenCalled()
+    })
+  })
+  describe('selector', () => {
+    const combinedReducer = combineSlices(stringSlice).withLazyLoadedSlices<{
+      boolean: boolean
+      counter: { value: number }
+    }>()
+
+    const uninjectedState = combinedReducer(undefined, dummyAction())
+
+    const injectedReducer = combinedReducer.inject({
+      reducerPath: 'boolean' as const,
+      reducer: booleanReducer,
+    })
+
+    it('ensures state is defined in selector even if action has not been dispatched', () => {
+      expect(uninjectedState.boolean).toBe(undefined)
+
+      const selectBoolean = injectedReducer.selector((state) => state.boolean)
+
+      expect(selectBoolean(uninjectedState)).toBe(
+        booleanReducer.getInitialState(),
+      )
+    })
+    it('exposes original to allow for logging', () => {
+      const selectBoolean = injectedReducer.selector(
+        (state) => injectedReducer.selector.original(state).boolean,
+      )
+      expect(selectBoolean(uninjectedState)).toBe(undefined)
+    })
+    it('throws if original is called on something other than state proxy', () => {
+      expect(() => injectedReducer.selector.original({} as any)).toThrow(
+        'original must be used on state Proxy',
+      )
+    })
+    it('allows passing a selectState selector, to handle nested state', () => {
+      const wrappedReducer = combineSlices({
+        inner: combinedReducer,
+      })
+
+      type RootState = ReturnType<typeof wrappedReducer>
+
+      const selector = injectedReducer.selector(
+        (state) => state.boolean,
+        (rootState: RootState) => rootState.inner,
+      )
+
+      expect(selector(wrappedReducer(undefined, dummyAction()))).toBe(
+        booleanReducer.getInitialState(),
+      )
+    })
+    it('caches initial state', () => {
+      const beforeInject = combinedReducer(undefined, dummyAction())
+      const injectedReducer = combinedReducer.inject(counterReducer)
+      const selectCounter = injectedReducer.selector((state) => state.counter)
+      const counter = selectCounter(beforeInject)
+      expect(counter).toBe(selectCounter(beforeInject))
+
+      injectedReducer.inject(
+        { reducerPath: 'counter', reducer: () => ({ value: 0 }) },
+        { overrideExisting: true },
+      )
+      const counter2 = selectCounter(beforeInject)
+      expect(counter2).not.toBe(counter)
+      expect(counter2).toBe(selectCounter(beforeInject))
+    })
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/combinedTest.test.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/combinedTest.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/combinedTest.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,133 @@
+import type { PayloadAction } from '@reduxjs/toolkit'
+import {
+  createAsyncThunk,
+  createAction,
+  createSlice,
+  configureStore,
+  createEntityAdapter,
+} from '@reduxjs/toolkit'
+import type { EntityAdapter } from '@internal/entities/models'
+import type { BookModel } from '@internal/entities/tests/fixtures/book'
+
+describe('Combined entity slice', () => {
+  let adapter: EntityAdapter<BookModel, string>
+
+  beforeEach(() => {
+    adapter = createEntityAdapter({
+      selectId: (book: BookModel) => book.id,
+      sortComparer: (a, b) => a.title.localeCompare(b.title),
+    })
+  })
+
+  it('Entity and async features all works together', async () => {
+    const upsertBook = createAction<BookModel>('otherBooks/upsert')
+
+    type BooksState = ReturnType<typeof adapter.getInitialState> & {
+      loading: 'initial' | 'pending' | 'finished' | 'failed'
+      lastRequestId: string | null
+    }
+
+    const initialState: BooksState = adapter.getInitialState({
+      loading: 'initial',
+      lastRequestId: null,
+    })
+
+    const fakeBooks: BookModel[] = [
+      { id: 'b', title: 'Second' },
+      { id: 'a', title: 'First' },
+    ]
+
+    const fetchBooksTAC = createAsyncThunk<
+      BookModel[],
+      void,
+      {
+        state: { books: BooksState }
+      }
+    >(
+      'books/fetch',
+      async (arg, { getState, dispatch, extra, requestId, signal }) => {
+        const state = getState()
+        return fakeBooks
+      },
+    )
+
+    const booksSlice = createSlice({
+      name: 'books',
+      initialState,
+      reducers: {
+        addOne: adapter.addOne,
+        removeOne(state, action: PayloadAction<string>) {
+          const sizeBefore = state.ids.length
+          // Originally, having nested `produce` calls don't mutate `state` here as I would have expected.
+          // (note that `state` here is actually an Immer Draft<S>, from `createReducer`)
+          // One woarkound was to return the new plain result value instead
+          // See https://github.com/immerjs/immer/issues/533
+          // However, after tweaking `createStateOperator` to check if the argument is a draft,
+          // we can just treat the operator as strictly mutating, without returning a result,
+          // and the result should be correct.
+          const result = adapter.removeOne(state, action)
+
+          const sizeAfter = state.ids.length
+          if (sizeBefore > 0) {
+            expect(sizeAfter).toBe(sizeBefore - 1)
+          }
+
+          //Deliberately _don't_ return result
+        },
+      },
+      extraReducers: (builder) => {
+        builder.addCase(upsertBook, (state, action) => {
+          return adapter.upsertOne(state, action)
+        })
+        builder.addCase(fetchBooksTAC.pending, (state, action) => {
+          state.loading = 'pending'
+          state.lastRequestId = action.meta.requestId
+        })
+        builder.addCase(fetchBooksTAC.fulfilled, (state, action) => {
+          if (
+            state.loading === 'pending' &&
+            action.meta.requestId === state.lastRequestId
+          ) {
+            adapter.setAll(state, action.payload)
+            state.loading = 'finished'
+            state.lastRequestId = null
+          }
+        })
+      },
+    })
+
+    const { addOne, removeOne } = booksSlice.actions
+    const { reducer } = booksSlice
+
+    const store = configureStore({
+      reducer: {
+        books: reducer,
+      },
+    })
+
+    await store.dispatch(fetchBooksTAC())
+
+    const { books: booksAfterLoaded } = store.getState()
+    // Sorted, so "First" goes first
+    expect(booksAfterLoaded.ids).toEqual(['a', 'b'])
+    expect(booksAfterLoaded.lastRequestId).toBe(null)
+    expect(booksAfterLoaded.loading).toBe('finished')
+
+    store.dispatch(addOne({ id: 'd', title: 'Remove Me' }))
+    store.dispatch(removeOne('d'))
+
+    store.dispatch(addOne({ id: 'c', title: 'Middle' }))
+
+    const { books: booksAfterAddOne } = store.getState()
+
+    // Sorted, so "Middle" goes in the middle
+    expect(booksAfterAddOne.ids).toEqual(['a', 'c', 'b'])
+
+    store.dispatch(upsertBook({ id: 'c', title: 'Zeroth' }))
+
+    const { books: booksAfterUpsert } = store.getState()
+
+    // Sorted, so "Zeroth" goes last
+    expect(booksAfterUpsert.ids).toEqual(['a', 'b', 'c'])
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/configureStore.test-d.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/configureStore.test-d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/configureStore.test-d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,805 @@
+import type {
+  Action,
+  ConfigureStoreOptions,
+  Dispatch,
+  Middleware,
+  PayloadAction,
+  Reducer,
+  Store,
+  StoreEnhancer,
+  ThunkAction,
+  ThunkDispatch,
+  ThunkMiddleware,
+  UnknownAction,
+} from '@reduxjs/toolkit'
+import {
+  Tuple,
+  applyMiddleware,
+  combineReducers,
+  configureStore,
+  createSlice,
+} from '@reduxjs/toolkit'
+import { thunk } from 'redux-thunk'
+
+const _anyMiddleware: any = () => () => () => {}
+
+describe('type tests', () => {
+  test('configureStore() requires a valid reducer or reducer map.', () => {
+    configureStore({
+      reducer: (state, action) => 0,
+    })
+
+    configureStore({
+      reducer: {
+        counter1: () => 0,
+        counter2: () => 1,
+      },
+    })
+
+    // @ts-expect-error
+    configureStore({ reducer: 'not a reducer' })
+
+    // @ts-expect-error
+    configureStore({ reducer: { a: 'not a reducer' } })
+
+    // @ts-expect-error
+    configureStore({})
+  })
+
+  test('configureStore() infers the store state type.', () => {
+    const reducer: Reducer<number> = () => 0
+
+    const store = configureStore({ reducer })
+
+    expectTypeOf(store).toMatchTypeOf<Store<number, UnknownAction>>()
+
+    expectTypeOf(store).not.toMatchTypeOf<Store<string, UnknownAction>>()
+  })
+
+  test('configureStore() infers the store action type.', () => {
+    const reducer: Reducer<number, PayloadAction<number>> = () => 0
+
+    const store = configureStore({ reducer })
+
+    expectTypeOf(store).toMatchTypeOf<Store<number, PayloadAction<number>>>()
+
+    expectTypeOf(store).not.toMatchTypeOf<
+      Store<number, PayloadAction<string>>
+    >()
+  })
+
+  test('configureStore() accepts Tuple for middleware, but not plain array.', () => {
+    const middleware: Middleware = (store) => (next) => next
+
+    configureStore({
+      reducer: () => 0,
+      middleware: () => new Tuple(middleware),
+    })
+
+    configureStore({
+      reducer: () => 0,
+      // @ts-expect-error
+      middleware: () => [middleware],
+    })
+
+    configureStore({
+      reducer: () => 0,
+      // @ts-expect-error
+      middleware: () => new Tuple('not middleware'),
+    })
+  })
+
+  test('configureStore() accepts devTools flag.', () => {
+    configureStore({
+      reducer: () => 0,
+      devTools: true,
+    })
+
+    configureStore({
+      reducer: () => 0,
+      // @ts-expect-error
+      devTools: 'true',
+    })
+  })
+
+  test('configureStore() accepts devTools EnhancerOptions.', () => {
+    configureStore({
+      reducer: () => 0,
+      devTools: { name: 'myApp' },
+    })
+
+    configureStore({
+      reducer: () => 0,
+      // @ts-expect-error
+      devTools: { appName: 'myApp' },
+    })
+  })
+
+  test('configureStore() accepts preloadedState.', () => {
+    configureStore({
+      reducer: () => 0,
+      preloadedState: 0,
+    })
+
+    configureStore({
+      // @ts-expect-error
+      reducer: (_: number) => 0,
+      preloadedState: 'non-matching state type',
+    })
+  })
+
+  test('nullable state is preserved', () => {
+    const store = configureStore({
+      reducer: (): string | null => null,
+    })
+
+    expectTypeOf(store.getState()).toEqualTypeOf<string | null>()
+  })
+
+  test('configureStore() accepts store Tuple for enhancers, but not plain array', () => {
+    const enhancer = applyMiddleware(() => (next) => next)
+
+    const store = configureStore({
+      reducer: () => 0,
+      enhancers: () => new Tuple(enhancer),
+    })
+
+    const store2 = configureStore({
+      reducer: () => 0,
+      // @ts-expect-error
+      enhancers: () => [enhancer],
+    })
+
+    expectTypeOf(store.dispatch).toMatchTypeOf<
+      Dispatch & ThunkDispatch<number, undefined, UnknownAction>
+    >()
+
+    configureStore({
+      reducer: () => 0,
+      // @ts-expect-error
+      enhancers: () => new Tuple('not a store enhancer'),
+    })
+
+    const somePropertyStoreEnhancer: StoreEnhancer<{
+      someProperty: string
+    }> = (next) => {
+      return (reducer, preloadedState) => {
+        return {
+          ...next(reducer, preloadedState),
+          someProperty: 'some value',
+        }
+      }
+    }
+
+    const anotherPropertyStoreEnhancer: StoreEnhancer<{
+      anotherProperty: number
+    }> = (next) => {
+      return (reducer, preloadedState) => {
+        return {
+          ...next(reducer, preloadedState),
+          anotherProperty: 123,
+        }
+      }
+    }
+
+    const store3 = configureStore({
+      reducer: () => 0,
+      enhancers: () =>
+        new Tuple(somePropertyStoreEnhancer, anotherPropertyStoreEnhancer),
+    })
+
+    expectTypeOf(store3.dispatch).toEqualTypeOf<Dispatch>()
+
+    expectTypeOf(store3.someProperty).toBeString()
+
+    expectTypeOf(store3.anotherProperty).toBeNumber()
+
+    const storeWithCallback = configureStore({
+      reducer: () => 0,
+      enhancers: (getDefaultEnhancers) =>
+        getDefaultEnhancers()
+          .prepend(anotherPropertyStoreEnhancer)
+          .concat(somePropertyStoreEnhancer),
+    })
+
+    expectTypeOf(store3.dispatch).toMatchTypeOf<
+      Dispatch & ThunkDispatch<number, undefined, UnknownAction>
+    >()
+
+    expectTypeOf(store3.someProperty).toBeString()
+
+    expectTypeOf(store3.anotherProperty).toBeNumber()
+
+    const someStateExtendingEnhancer: StoreEnhancer<
+      {},
+      { someProperty: string }
+    > =
+      (next) =>
+      (...args) => {
+        const store = next(...args)
+        const getState = () => ({
+          ...store.getState(),
+          someProperty: 'some value',
+        })
+        return {
+          ...store,
+          getState,
+        } as any
+      }
+
+    const anotherStateExtendingEnhancer: StoreEnhancer<
+      {},
+      { anotherProperty: number }
+    > =
+      (next) =>
+      (...args) => {
+        const store = next(...args)
+        const getState = () => ({
+          ...store.getState(),
+          anotherProperty: 123,
+        })
+        return {
+          ...store,
+          getState,
+        } as any
+      }
+
+    const store4 = configureStore({
+      reducer: () => ({ aProperty: 0 }),
+      enhancers: () =>
+        new Tuple(someStateExtendingEnhancer, anotherStateExtendingEnhancer),
+    })
+
+    const state = store4.getState()
+
+    expectTypeOf(state.aProperty).toBeNumber()
+
+    expectTypeOf(state.someProperty).toBeString()
+
+    expectTypeOf(state.anotherProperty).toBeNumber()
+
+    const storeWithCallback2 = configureStore({
+      reducer: () => ({ aProperty: 0 }),
+      enhancers: (gDE) =>
+        gDE().concat(someStateExtendingEnhancer, anotherStateExtendingEnhancer),
+    })
+
+    const stateWithCallback = storeWithCallback2.getState()
+
+    expectTypeOf(stateWithCallback.aProperty).toBeNumber()
+
+    expectTypeOf(stateWithCallback.someProperty).toBeString()
+
+    expectTypeOf(stateWithCallback.anotherProperty).toBeNumber()
+  })
+
+  test('Preloaded state typings', () => {
+    const counterReducer1: Reducer<number> = () => 0
+    const counterReducer2: Reducer<number> = () => 0
+
+    test('partial preloaded state', () => {
+      const store = configureStore({
+        reducer: {
+          counter1: counterReducer1,
+          counter2: counterReducer2,
+        },
+        preloadedState: {
+          counter1: 0,
+        },
+      })
+
+      expectTypeOf(store.getState().counter1).toBeNumber()
+
+      expectTypeOf(store.getState().counter2).toBeNumber()
+    })
+
+    test('empty preloaded state', () => {
+      const store = configureStore({
+        reducer: {
+          counter1: counterReducer1,
+          counter2: counterReducer2,
+        },
+        preloadedState: {},
+      })
+
+      expectTypeOf(store.getState().counter1).toBeNumber()
+
+      expectTypeOf(store.getState().counter2).toBeNumber()
+    })
+
+    test('excess properties in preloaded state', () => {
+      const store = configureStore({
+        reducer: {
+          // @ts-expect-error
+          counter1: counterReducer1,
+          counter2: counterReducer2,
+        },
+        preloadedState: {
+          counter1: 0,
+          counter3: 5,
+        },
+      })
+
+      expectTypeOf(store.getState().counter1).toBeNumber()
+
+      expectTypeOf(store.getState().counter2).toBeNumber()
+    })
+
+    test('mismatching properties in preloaded state', () => {
+      const store = configureStore({
+        reducer: {
+          // @ts-expect-error
+          counter1: counterReducer1,
+          counter2: counterReducer2,
+        },
+        preloadedState: {
+          counter3: 5,
+        },
+      })
+
+      expectTypeOf(store.getState().counter1).toBeNumber()
+
+      expectTypeOf(store.getState().counter2).toBeNumber()
+    })
+
+    test('string preloaded state when expecting object', () => {
+      const store = configureStore({
+        reducer: {
+          // @ts-expect-error
+          counter1: counterReducer1,
+          counter2: counterReducer2,
+        },
+        preloadedState: 'test',
+      })
+
+      expectTypeOf(store.getState().counter1).toBeNumber()
+
+      expectTypeOf(store.getState().counter2).toBeNumber()
+    })
+
+    test('nested combineReducers allows partial', () => {
+      const store = configureStore({
+        reducer: {
+          group1: combineReducers({
+            counter1: counterReducer1,
+            counter2: counterReducer2,
+          }),
+          group2: combineReducers({
+            counter1: counterReducer1,
+            counter2: counterReducer2,
+          }),
+        },
+        preloadedState: {
+          group1: {
+            counter1: 5,
+          },
+        },
+      })
+
+      expectTypeOf(store.getState().group1.counter1).toBeNumber()
+
+      expectTypeOf(store.getState().group1.counter2).toBeNumber()
+
+      expectTypeOf(store.getState().group2.counter1).toBeNumber()
+
+      expectTypeOf(store.getState().group2.counter2).toBeNumber()
+    })
+
+    test('non-nested combineReducers does not allow partial', () => {
+      interface GroupState {
+        counter1: number
+        counter2: number
+      }
+
+      const initialState = { counter1: 0, counter2: 0 }
+
+      const group1Reducer: Reducer<GroupState> = (state = initialState) => state
+      const group2Reducer: Reducer<GroupState> = (state = initialState) => state
+
+      const store = configureStore({
+        reducer: {
+          // @ts-expect-error
+          group1: group1Reducer,
+          group2: group2Reducer,
+        },
+        preloadedState: {
+          group1: {
+            counter1: 5,
+          },
+        },
+      })
+
+      expectTypeOf(store.getState().group1.counter1).toBeNumber()
+
+      expectTypeOf(store.getState().group1.counter2).toBeNumber()
+
+      expectTypeOf(store.getState().group2.counter1).toBeNumber()
+
+      expectTypeOf(store.getState().group2.counter2).toBeNumber()
+    })
+  })
+
+  test('Dispatch typings', () => {
+    type StateA = number
+    const reducerA = () => 0
+    const thunkA = () => {
+      return (() => {}) as any as ThunkAction<Promise<'A'>, StateA, any, any>
+    }
+
+    type StateB = string
+    const thunkB = () => {
+      return (dispatch: Dispatch, getState: () => StateB) => {}
+    }
+
+    test('by default, dispatching Thunks is possible', () => {
+      const store = configureStore({
+        reducer: reducerA,
+      })
+
+      store.dispatch(thunkA())
+      // @ts-expect-error
+      store.dispatch(thunkB())
+
+      const res = store.dispatch((dispatch, getState) => {
+        return 42
+      })
+
+      const action = store.dispatch({ type: 'foo' })
+    })
+
+    test('return type of thunks and actions is inferred correctly', () => {
+      const slice = createSlice({
+        name: 'counter',
+        initialState: {
+          value: 0,
+        },
+        reducers: {
+          incrementByAmount: (state, action: PayloadAction<number>) => {
+            state.value += action.payload
+          },
+        },
+      })
+
+      const store = configureStore({
+        reducer: {
+          counter: slice.reducer,
+        },
+      })
+
+      const action = slice.actions.incrementByAmount(2)
+
+      const dispatchResult = store.dispatch(action)
+
+      expectTypeOf(dispatchResult).toMatchTypeOf<{
+        type: string
+        payload: number
+      }>()
+
+      const promiseResult = store.dispatch(async (dispatch) => {
+        return 42
+      })
+
+      expectTypeOf(promiseResult).toEqualTypeOf<Promise<number>>()
+
+      const store2 = configureStore({
+        reducer: {
+          counter: slice.reducer,
+        },
+        middleware: (gDM) =>
+          gDM({
+            thunk: {
+              extraArgument: 42,
+            },
+          }),
+      })
+
+      const dispatchResult2 = store2.dispatch(action)
+
+      expectTypeOf(dispatchResult2).toMatchTypeOf<{
+        type: string
+        payload: number
+      }>()
+    })
+
+    test('removing the Thunk Middleware', () => {
+      const store = configureStore({
+        reducer: reducerA,
+        middleware: () => new Tuple(),
+      })
+
+      expectTypeOf(store.dispatch).parameter(0).not.toMatchTypeOf(thunkA())
+
+      expectTypeOf(store.dispatch).parameter(0).not.toMatchTypeOf(thunkB())
+    })
+
+    test('adding the thunk middleware by hand', () => {
+      const store = configureStore({
+        reducer: reducerA,
+        middleware: () => new Tuple(thunk as ThunkMiddleware<StateA>),
+      })
+
+      store.dispatch(thunkA())
+      // @ts-expect-error
+      store.dispatch(thunkB())
+    })
+
+    test('custom middleware', () => {
+      const store = configureStore({
+        reducer: reducerA,
+        middleware: () =>
+          new Tuple(0 as unknown as Middleware<(a: StateA) => boolean, StateA>),
+      })
+
+      expectTypeOf(store.dispatch(5)).toBeBoolean()
+
+      expectTypeOf(store.dispatch(5)).not.toBeString()
+    })
+
+    test('multiple custom middleware', () => {
+      const middleware = [] as any as Tuple<
+        [
+          Middleware<(a: 'a') => 'A', StateA>,
+          Middleware<(b: 'b') => 'B', StateA>,
+          ThunkMiddleware<StateA>,
+        ]
+      >
+
+      const store = configureStore({
+        reducer: reducerA,
+        middleware: () => middleware,
+      })
+
+      expectTypeOf(store.dispatch('a')).toEqualTypeOf<'A'>()
+
+      expectTypeOf(store.dispatch('b')).toEqualTypeOf<'B'>()
+
+      expectTypeOf(store.dispatch(thunkA())).toEqualTypeOf<Promise<'A'>>()
+    })
+
+    test('Accepts thunk with `unknown`, `undefined` or `null` ThunkAction extraArgument per default', () => {
+      const store = configureStore({ reducer: {} })
+      // undefined is the default value for the ThunkMiddleware extraArgument
+      store.dispatch(function () {} as ThunkAction<
+        void,
+        {},
+        undefined,
+        UnknownAction
+      >)
+      // `null` for the `extra` generic was previously documented in the RTK "Advanced Tutorial", but
+      // is a bad pattern and users should use `unknown` instead
+      // @ts-expect-error
+      store.dispatch(function () {} as ThunkAction<
+        void,
+        {},
+        null,
+        UnknownAction
+      >)
+      // unknown is the best way to type a ThunkAction if you do not care
+      // about the value of the extraArgument, as it will always work with every
+      // ThunkMiddleware, no matter the actual extraArgument type
+      store.dispatch(function () {} as ThunkAction<
+        void,
+        {},
+        unknown,
+        UnknownAction
+      >)
+      // @ts-expect-error
+      store.dispatch(function () {} as ThunkAction<
+        void,
+        {},
+        boolean,
+        UnknownAction
+      >)
+    })
+
+    test('custom middleware and getDefaultMiddleware', () => {
+      const store = configureStore({
+        reducer: reducerA,
+        middleware: (gDM) =>
+          gDM().prepend((() => {}) as any as Middleware<
+            (a: 'a') => 'A',
+            StateA
+          >),
+      })
+
+      expectTypeOf(store.dispatch('a')).toEqualTypeOf<'A'>()
+
+      expectTypeOf(store.dispatch(thunkA())).toEqualTypeOf<Promise<'A'>>()
+
+      expectTypeOf(store.dispatch).parameter(0).not.toMatchTypeOf(thunkB())
+    })
+
+    test('custom middleware and getDefaultMiddleware, using prepend', () => {
+      const otherMiddleware: Middleware<(a: 'a') => 'A', StateA> =
+        _anyMiddleware
+
+      const store = configureStore({
+        reducer: reducerA,
+        middleware: (gDM) => {
+          const concatenated = gDM().prepend(otherMiddleware)
+
+          expectTypeOf(concatenated).toMatchTypeOf<
+            ReadonlyArray<
+              typeof otherMiddleware | ThunkMiddleware | Middleware<{}>
+            >
+          >()
+
+          return concatenated
+        },
+      })
+
+      expectTypeOf(store.dispatch('a')).toEqualTypeOf<'A'>()
+
+      expectTypeOf(store.dispatch(thunkA())).toEqualTypeOf<Promise<'A'>>()
+
+      expectTypeOf(store.dispatch).parameter(0).not.toMatchTypeOf(thunkB())
+    })
+
+    test('custom middleware and getDefaultMiddleware, using concat', () => {
+      const otherMiddleware: Middleware<(a: 'a') => 'A', StateA> =
+        _anyMiddleware
+
+      const store = configureStore({
+        reducer: reducerA,
+        middleware: (gDM) => {
+          const concatenated = gDM().concat(otherMiddleware)
+
+          expectTypeOf(concatenated).toMatchTypeOf<
+            ReadonlyArray<
+              typeof otherMiddleware | ThunkMiddleware | Middleware<{}>
+            >
+          >()
+
+          return concatenated
+        },
+      })
+
+      expectTypeOf(store.dispatch('a')).toEqualTypeOf<'A'>()
+
+      expectTypeOf(store.dispatch(thunkA())).toEqualTypeOf<Promise<'A'>>()
+
+      expectTypeOf(store.dispatch).parameter(0).not.toMatchTypeOf(thunkB())
+    })
+
+    test('middlewareBuilder notation, getDefaultMiddleware (unconfigured)', () => {
+      const store = configureStore({
+        reducer: reducerA,
+        middleware: (getDefaultMiddleware) =>
+          getDefaultMiddleware().prepend((() => {}) as any as Middleware<
+            (a: 'a') => 'A',
+            StateA
+          >),
+      })
+
+      expectTypeOf(store.dispatch('a')).toEqualTypeOf<'A'>()
+
+      expectTypeOf(store.dispatch(thunkA())).toEqualTypeOf<Promise<'A'>>()
+
+      expectTypeOf(store.dispatch).parameter(0).not.toMatchTypeOf(thunkB())
+    })
+
+    test('middlewareBuilder notation, getDefaultMiddleware, concat & prepend', () => {
+      const otherMiddleware: Middleware<(a: 'a') => 'A', StateA> =
+        _anyMiddleware
+
+      const otherMiddleware2: Middleware<(a: 'b') => 'B', StateA> =
+        _anyMiddleware
+
+      const store = configureStore({
+        reducer: reducerA,
+        middleware: (getDefaultMiddleware) =>
+          getDefaultMiddleware()
+            .concat(otherMiddleware)
+            .prepend(otherMiddleware2),
+      })
+
+      expectTypeOf(store.dispatch('a')).toEqualTypeOf<'A'>()
+
+      expectTypeOf(store.dispatch(thunkA())).toEqualTypeOf<Promise<'A'>>()
+
+      expectTypeOf(store.dispatch('b')).toEqualTypeOf<'B'>()
+
+      expectTypeOf(store.dispatch).parameter(0).not.toMatchTypeOf(thunkB())
+    })
+
+    test('middlewareBuilder notation, getDefaultMiddleware (thunk: false)', () => {
+      const store = configureStore({
+        reducer: reducerA,
+        middleware: (getDefaultMiddleware) =>
+          getDefaultMiddleware({ thunk: false }).prepend(
+            (() => {}) as any as Middleware<(a: 'a') => 'A', StateA>,
+          ),
+      })
+
+      expectTypeOf(store.dispatch('a')).toEqualTypeOf<'A'>()
+
+      expectTypeOf(store.dispatch).parameter(0).not.toMatchTypeOf(thunkA())
+    })
+
+    test("badly typed middleware won't make `dispatch` `any`", () => {
+      const store = configureStore({
+        reducer: reducerA,
+        middleware: (getDefaultMiddleware) =>
+          getDefaultMiddleware().concat(_anyMiddleware as Middleware<any>),
+      })
+
+      expectTypeOf(store.dispatch).not.toBeAny()
+    })
+
+    test("decorated `configureStore` won't make `dispatch` `never`", () => {
+      const someSlice = createSlice({
+        name: 'something',
+        initialState: null as any,
+        reducers: {
+          set(state) {
+            return state
+          },
+        },
+      })
+
+      function configureMyStore<S>(
+        options: Omit<ConfigureStoreOptions<S>, 'reducer'>,
+      ) {
+        return configureStore({
+          ...options,
+          reducer: someSlice.reducer,
+        })
+      }
+
+      const store = configureMyStore({})
+
+      expectTypeOf(store.dispatch).toBeFunction()
+    })
+
+    interface CounterState {
+      value: number
+    }
+
+    const counterSlice = createSlice({
+      name: 'counter',
+      initialState: { value: 0 } as CounterState,
+      reducers: {
+        increment(state) {
+          state.value += 1
+        },
+        decrement(state) {
+          state.value -= 1
+        },
+        // Use the PayloadAction type to declare the contents of `action.payload`
+        incrementByAmount: (state, action: PayloadAction<number>) => {
+          state.value += action.payload
+        },
+      },
+    })
+
+    type Unsubscribe = () => void
+
+    // A fake middleware that tells TS that an unsubscribe callback is being returned for a given action
+    // This is the same signature that the "listener" middleware uses
+    const dummyMiddleware: Middleware<
+      {
+        (action: Action<'actionListenerMiddleware/add'>): Unsubscribe
+      },
+      CounterState
+    > = (storeApi) => (next) => (action) => {}
+
+    const store = configureStore({
+      reducer: counterSlice.reducer,
+      middleware: (gDM) => gDM().prepend(dummyMiddleware),
+    })
+
+    // Order matters here! We need the listener type to come first, otherwise
+    // the thunk middleware type kicks in and TS thinks a plain action is being returned
+    expectTypeOf(store.dispatch).toEqualTypeOf<
+      ((action: Action<'actionListenerMiddleware/add'>) => Unsubscribe) &
+        ThunkDispatch<CounterState, undefined, UnknownAction> &
+        Dispatch<UnknownAction>
+    >()
+
+    const unsubscribe = store.dispatch({
+      type: 'actionListenerMiddleware/add',
+    } as const)
+
+    expectTypeOf(unsubscribe).toEqualTypeOf<Unsubscribe>()
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/configureStore.test.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/configureStore.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/configureStore.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,371 @@
+import * as DevTools from '@internal/devtoolsExtension'
+import type { Middleware, StoreEnhancer } from '@reduxjs/toolkit'
+import { Tuple } from '@reduxjs/toolkit'
+import type * as Redux from 'redux'
+import { vi } from 'vitest'
+
+vi.doMock('redux', async (importOriginal) => {
+  const redux = await importOriginal<typeof import('redux')>()
+
+  vi.spyOn(redux, 'applyMiddleware')
+  vi.spyOn(redux, 'combineReducers')
+  vi.spyOn(redux, 'compose')
+  vi.spyOn(redux, 'createStore')
+
+  return redux
+})
+
+describe('configureStore', async () => {
+  const composeWithDevToolsSpy = vi.spyOn(DevTools, 'composeWithDevTools')
+
+  const redux = await import('redux')
+
+  const { configureStore } = await import('@reduxjs/toolkit')
+
+  const reducer: Redux.Reducer = (state = {}, _action) => state
+
+  beforeEach(() => {
+    vi.clearAllMocks()
+  })
+
+  describe('given a function reducer', () => {
+    it('calls createStore with the reducer', () => {
+      configureStore({ reducer })
+      expect(configureStore({ reducer })).toBeInstanceOf(Object)
+
+      expect(redux.createStore).toHaveBeenCalledWith(
+        reducer,
+        undefined,
+        expect.any(Function),
+      )
+      expect(redux.applyMiddleware).toHaveBeenCalled()
+      if (process.env.TEST_DIST) {
+        expect(composeWithDevToolsSpy).not.toHaveBeenCalled()
+      } else {
+        expect(composeWithDevToolsSpy).toHaveBeenCalledTimes(2)
+      }
+    })
+  })
+
+  describe('given an object of reducers', () => {
+    it('calls createStore with the combined reducers', () => {
+      const reducer = {
+        reducer() {
+          return true
+        },
+      }
+      expect(configureStore({ reducer })).toBeInstanceOf(Object)
+      expect(redux.combineReducers).toHaveBeenCalledWith(reducer)
+      expect(redux.applyMiddleware).toHaveBeenCalled()
+      if (process.env.TEST_DIST) {
+        expect(composeWithDevToolsSpy).not.toHaveBeenCalled()
+      } else {
+        expect(composeWithDevToolsSpy).toHaveBeenCalledOnce()
+      }
+      expect(redux.createStore).toHaveBeenCalledWith(
+        expect.any(Function),
+        undefined,
+        expect.any(Function),
+      )
+    })
+  })
+
+  describe('given no reducer', () => {
+    it('throws', () => {
+      expect(configureStore).toThrow(
+        '`reducer` is a required argument, and must be a function or an object of functions that can be passed to combineReducers',
+      )
+    })
+  })
+
+  describe('given no middleware', () => {
+    it('calls createStore without any middleware', () => {
+      expect(
+        configureStore({ middleware: () => new Tuple(), reducer }),
+      ).toBeInstanceOf(Object)
+      expect(redux.applyMiddleware).toHaveBeenCalledWith()
+      if (process.env.TEST_DIST) {
+        expect(composeWithDevToolsSpy).not.toHaveBeenCalled()
+      } else {
+        expect(composeWithDevToolsSpy).toHaveBeenCalledOnce()
+      }
+      expect(redux.createStore).toHaveBeenCalledWith(
+        reducer,
+        undefined,
+        expect.any(Function),
+      )
+    })
+  })
+
+  describe('given an array of middleware', () => {
+    it('throws an error requiring a callback', () => {
+      // @ts-expect-error
+      expect(() => configureStore({ middleware: [], reducer })).toThrow(
+        '`middleware` field must be a callback',
+      )
+    })
+  })
+
+  describe('given undefined middleware', () => {
+    it('calls createStore with default middleware', () => {
+      expect(configureStore({ middleware: undefined, reducer })).toBeInstanceOf(
+        Object,
+      )
+      expect(redux.applyMiddleware).toHaveBeenCalledWith(
+        expect.any(Function), // immutableCheck
+        expect.any(Function), // thunk
+        expect.any(Function), // serializableCheck
+        expect.any(Function), // actionCreatorCheck
+      )
+      if (process.env.TEST_DIST) {
+        expect(composeWithDevToolsSpy).not.toHaveBeenCalled()
+      } else {
+        expect(composeWithDevToolsSpy).toHaveBeenCalledOnce()
+      }
+      expect(redux.createStore).toHaveBeenCalledWith(
+        reducer,
+        undefined,
+        expect.any(Function),
+      )
+    })
+  })
+
+  describe('given any middleware', () => {
+    const exampleMiddleware: Middleware<any, any> = () => (next) => (action) =>
+      next(action)
+    it('throws an error by default if there are duplicate middleware', () => {
+      const makeStore = () => {
+        return configureStore({
+          reducer,
+          middleware: (gDM) =>
+            gDM().concat(exampleMiddleware, exampleMiddleware),
+        })
+      }
+
+      expect(makeStore).toThrowError(
+        'Duplicate middleware references found when creating the store. Ensure that each middleware is only included once.',
+      )
+    })
+
+    it('does not throw a duplicate middleware error if duplicateMiddlewareCheck is disabled', () => {
+      const makeStore = () => {
+        return configureStore({
+          reducer,
+          middleware: (gDM) =>
+            gDM().concat(exampleMiddleware, exampleMiddleware),
+          duplicateMiddlewareCheck: false,
+        })
+      }
+
+      expect(makeStore).not.toThrowError()
+    })
+  })
+
+  describe('given a middleware creation function that returns undefined', () => {
+    it('throws an error', () => {
+      const invalidBuilder = vi.fn((getDefaultMiddleware) => undefined as any)
+      expect(() =>
+        configureStore({ middleware: invalidBuilder, reducer }),
+      ).toThrow(
+        'when using a middleware builder function, an array of middleware must be returned',
+      )
+    })
+  })
+
+  describe('given a middleware creation function that returns an array with non-functions', () => {
+    it('throws an error', () => {
+      const invalidBuilder = vi.fn((getDefaultMiddleware) => [true] as any)
+      expect(() =>
+        configureStore({ middleware: invalidBuilder, reducer }),
+      ).toThrow('each middleware provided to configureStore must be a function')
+    })
+  })
+
+  describe('given custom middleware', () => {
+    it('calls createStore with custom middleware and without default middleware', () => {
+      const thank: Redux.Middleware = (_store) => (next) => (action) =>
+        next(action)
+      expect(
+        configureStore({ middleware: () => new Tuple(thank), reducer }),
+      ).toBeInstanceOf(Object)
+      expect(redux.applyMiddleware).toHaveBeenCalledWith(thank)
+      if (process.env.TEST_DIST) {
+        expect(composeWithDevToolsSpy).not.toHaveBeenCalled()
+      } else {
+        expect(composeWithDevToolsSpy).toHaveBeenCalledOnce()
+      }
+      expect(redux.createStore).toHaveBeenCalledWith(
+        reducer,
+        undefined,
+        expect.any(Function),
+      )
+    })
+  })
+
+  describe('middleware builder notation', () => {
+    it('calls builder, passes getDefaultMiddleware and uses returned middlewares', () => {
+      const thank = vi.fn(
+        ((_store) => (next) => (action) => 'foobar') as Redux.Middleware,
+      )
+
+      const builder = vi.fn((getDefaultMiddleware) => {
+        expect(getDefaultMiddleware).toEqual(expect.any(Function))
+        expect(getDefaultMiddleware()).toEqual(expect.any(Array))
+
+        return new Tuple(thank)
+      })
+
+      const store = configureStore({ middleware: builder, reducer })
+
+      expect(builder).toHaveBeenCalled()
+
+      expect(store.dispatch({ type: 'test' })).toBe('foobar')
+    })
+  })
+
+  describe('with devTools disabled', () => {
+    it('calls createStore without devTools enhancer', () => {
+      expect(configureStore({ devTools: false, reducer })).toBeInstanceOf(
+        Object,
+      )
+      expect(redux.applyMiddleware).toHaveBeenCalled()
+      expect(redux.compose).toHaveBeenCalled()
+      expect(redux.createStore).toHaveBeenCalledWith(
+        reducer,
+        undefined,
+        expect.any(Function),
+      )
+    })
+  })
+
+  describe('with devTools options', () => {
+    it('calls createStore with devTools enhancer and option', () => {
+      const options = {
+        name: 'myApp',
+        trace: true,
+      }
+      expect(configureStore({ devTools: options, reducer })).toBeInstanceOf(
+        Object,
+      )
+      expect(redux.applyMiddleware).toHaveBeenCalled()
+      if (process.env.TEST_DIST) {
+        expect(composeWithDevToolsSpy).not.toHaveBeenCalled()
+      } else {
+        expect(composeWithDevToolsSpy).toHaveBeenCalledOnce()
+
+        expect(composeWithDevToolsSpy).toHaveBeenLastCalledWith(options)
+      }
+      expect(redux.createStore).toHaveBeenCalledWith(
+        reducer,
+        undefined,
+        expect.any(Function),
+      )
+    })
+  })
+
+  describe('given preloadedState', () => {
+    it('calls createStore with preloadedState', () => {
+      expect(configureStore({ reducer })).toBeInstanceOf(Object)
+      expect(redux.applyMiddleware).toHaveBeenCalled()
+      if (process.env.TEST_DIST) {
+        expect(composeWithDevToolsSpy).not.toHaveBeenCalled()
+      } else {
+        expect(composeWithDevToolsSpy).toHaveBeenCalledOnce()
+      }
+      expect(redux.createStore).toHaveBeenCalledWith(
+        reducer,
+        undefined,
+        expect.any(Function),
+      )
+    })
+  })
+
+  describe('given enhancers', () => {
+    let dummyEnhancerCalled = false
+
+    const dummyEnhancer: StoreEnhancer =
+      (createStore) => (reducer, preloadedState) => {
+        dummyEnhancerCalled = true
+
+        return createStore(reducer, preloadedState)
+      }
+
+    beforeEach(() => {
+      dummyEnhancerCalled = false
+    })
+
+    it('calls createStore with enhancers', () => {
+      expect(
+        configureStore({
+          enhancers: (gDE) => gDE().concat(dummyEnhancer),
+          reducer,
+        }),
+      ).toBeInstanceOf(Object)
+      expect(redux.applyMiddleware).toHaveBeenCalled()
+      if (process.env.TEST_DIST) {
+        expect(composeWithDevToolsSpy).not.toHaveBeenCalled()
+      } else {
+        expect(composeWithDevToolsSpy).toHaveBeenCalledOnce()
+      }
+      expect(redux.createStore).toHaveBeenCalledWith(
+        reducer,
+        undefined,
+        expect.any(Function),
+      )
+
+      expect(dummyEnhancerCalled).toBe(true)
+    })
+
+    describe('invalid arguments', () => {
+      test('enhancers is not a callback', () => {
+        expect(() => configureStore({ reducer, enhancers: [] as any })).toThrow(
+          '`enhancers` field must be a callback',
+        )
+      })
+
+      test('callback fails to return array', () => {
+        expect(() =>
+          configureStore({ reducer, enhancers: (() => {}) as any }),
+        ).toThrow('`enhancers` callback must return an array')
+      })
+
+      test('array contains non-function', () => {
+        expect(() =>
+          configureStore({ reducer, enhancers: (() => ['']) as any }),
+        ).toThrow('each enhancer provided to configureStore must be a function')
+      })
+    })
+
+    const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
+    beforeEach(() => {
+      consoleSpy.mockClear()
+    })
+    afterAll(() => {
+      consoleSpy.mockRestore()
+    })
+
+    it('warns if middleware enhancer is excluded from final array when middlewares are provided', () => {
+      const store = configureStore({
+        reducer,
+        enhancers: () => new Tuple(dummyEnhancer),
+      })
+
+      expect(dummyEnhancerCalled).toBe(true)
+
+      expect(consoleSpy).toHaveBeenCalledWith(
+        'middlewares were provided, but middleware enhancer was not included in final enhancers - make sure to call `getDefaultEnhancers`',
+      )
+    })
+    it("doesn't warn when middleware enhancer is excluded if no middlewares provided", () => {
+      const store = configureStore({
+        reducer,
+        middleware: () => new Tuple(),
+        enhancers: () => new Tuple(dummyEnhancer),
+      })
+
+      expect(dummyEnhancerCalled).toBe(true)
+
+      expect(consoleSpy).not.toHaveBeenCalled()
+    })
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/createAction.test-d.tsx
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/createAction.test-d.tsx	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/createAction.test-d.tsx	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,326 @@
+import type {
+  Action,
+  ActionCreator,
+  ActionCreatorWithNonInferrablePayload,
+  ActionCreatorWithOptionalPayload,
+  ActionCreatorWithPayload,
+  ActionCreatorWithPreparedPayload,
+  ActionCreatorWithoutPayload,
+  PayloadAction,
+  PayloadActionCreator,
+  UnknownAction,
+} from '@reduxjs/toolkit'
+import { createAction } from '@reduxjs/toolkit'
+
+describe('type tests', () => {
+  describe('PayloadAction', () => {
+    test('PayloadAction has type parameter for the payload.', () => {
+      const action: PayloadAction<number> = { type: '', payload: 5 }
+
+      expectTypeOf(action.payload).toBeNumber()
+
+      expectTypeOf(action.payload).not.toBeString()
+    })
+
+    test('PayloadAction type parameter is required.', () => {
+      expectTypeOf({ type: '', payload: 5 }).not.toMatchTypeOf<PayloadAction>()
+    })
+
+    test('PayloadAction has a string type tag.', () => {
+      expectTypeOf({ type: '', payload: 5 }).toEqualTypeOf<
+        PayloadAction<number>
+      >()
+
+      expectTypeOf({ type: 1, payload: 5 }).not.toMatchTypeOf<PayloadAction>()
+    })
+
+    test('PayloadAction is compatible with Action<string>', () => {
+      const action: PayloadAction<number> = { type: '', payload: 5 }
+
+      expectTypeOf(action).toMatchTypeOf<Action<string>>()
+    })
+  })
+
+  describe('PayloadActionCreator', () => {
+    test('PayloadActionCreator returns correctly typed PayloadAction depending on whether a payload is passed.', () => {
+      const actionCreator = Object.assign(
+        (payload?: number) => ({
+          type: 'action',
+          payload,
+        }),
+        { type: 'action' },
+      ) as PayloadActionCreator<number | undefined>
+
+      expectTypeOf(actionCreator(1)).toEqualTypeOf<
+        PayloadAction<number | undefined>
+      >()
+
+      expectTypeOf(actionCreator()).toEqualTypeOf<
+        PayloadAction<number | undefined>
+      >()
+
+      expectTypeOf(actionCreator(undefined)).toEqualTypeOf<
+        PayloadAction<number | undefined>
+      >()
+
+      expectTypeOf(actionCreator()).not.toMatchTypeOf<PayloadAction<number>>()
+
+      expectTypeOf(actionCreator(1)).not.toMatchTypeOf<
+        PayloadAction<undefined>
+      >()
+    })
+
+    test('PayloadActionCreator is compatible with ActionCreator.', () => {
+      const payloadActionCreator = Object.assign(
+        (payload?: number) => ({
+          type: 'action',
+          payload,
+        }),
+        { type: 'action' },
+      ) as PayloadActionCreator
+
+      expectTypeOf(payloadActionCreator).toMatchTypeOf<
+        ActionCreator<UnknownAction>
+      >()
+
+      const payloadActionCreator2 = Object.assign(
+        (payload?: number) => ({
+          type: 'action',
+          payload: payload || 1,
+        }),
+        { type: 'action' },
+      ) as PayloadActionCreator<number>
+
+      expectTypeOf(payloadActionCreator2).toMatchTypeOf<
+        ActionCreator<PayloadAction<number>>
+      >()
+    })
+  })
+
+  test('createAction() has type parameter for the action payload.', () => {
+    const increment = createAction<number, 'increment'>('increment')
+
+    expectTypeOf(increment).parameter(0).toBeNumber()
+
+    expectTypeOf(increment).parameter(0).not.toBeString()
+  })
+
+  test('createAction() type parameter is required, not inferred (defaults to `void`).', () => {
+    const increment = createAction('increment')
+
+    expectTypeOf(increment).parameter(0).not.toBeNumber()
+
+    expectTypeOf(increment().payload).not.toBeNumber()
+  })
+
+  test('createAction().type is a string literal.', () => {
+    const increment = createAction<number, 'increment'>('increment')
+
+    expectTypeOf(increment(1).type).toBeString()
+
+    expectTypeOf(increment(1).type).toEqualTypeOf<'increment'>()
+
+    expectTypeOf(increment(1).type).not.toMatchTypeOf<'other'>()
+
+    expectTypeOf(increment(1).type).not.toBeNumber()
+  })
+
+  test('type still present when using prepareAction', () => {
+    const strLenAction = createAction('strLen', (payload: string) => ({
+      payload: payload.length,
+    }))
+
+    expectTypeOf(strLenAction('test').type).toBeString()
+  })
+
+  test('changing payload type with prepareAction', () => {
+    const strLenAction = createAction('strLen', (payload: string) => ({
+      payload: payload.length,
+    }))
+
+    expectTypeOf(strLenAction('test').payload).toBeNumber()
+
+    expectTypeOf(strLenAction('test').payload).not.toBeString()
+
+    expectTypeOf(strLenAction('test')).not.toHaveProperty('error')
+  })
+
+  test('adding metadata with prepareAction', () => {
+    const strLenMetaAction = createAction('strLenMeta', (payload: string) => ({
+      payload,
+      meta: payload.length,
+    }))
+
+    expectTypeOf(strLenMetaAction('test').meta).toBeNumber()
+
+    expectTypeOf(strLenMetaAction('test').meta).not.toBeString()
+
+    expectTypeOf(strLenMetaAction('test')).not.toHaveProperty('error')
+  })
+
+  test('adding boolean error with prepareAction', () => {
+    const boolErrorAction = createAction('boolError', (payload: string) => ({
+      payload,
+      error: true,
+    }))
+
+    expectTypeOf(boolErrorAction('test').error).toBeBoolean()
+
+    expectTypeOf(boolErrorAction('test').error).not.toBeString()
+  })
+
+  test('adding string error with prepareAction', () => {
+    const strErrorAction = createAction('strError', (payload: string) => ({
+      payload,
+      error: 'this is an error',
+    }))
+
+    expectTypeOf(strErrorAction('test').error).toBeString()
+
+    expectTypeOf(strErrorAction('test').error).not.toBeBoolean()
+  })
+
+  test('regression test for https://github.com/reduxjs/redux-toolkit/issues/214', () => {
+    const action = createAction<{ input?: string }>('ACTION')
+
+    expectTypeOf(action({ input: '' }).payload.input).toEqualTypeOf<
+      string | undefined
+    >()
+
+    expectTypeOf(action({ input: '' }).payload.input).not.toBeNumber()
+
+    expectTypeOf(action).parameter(0).not.toMatchTypeOf({ input: 3 })
+  })
+
+  test('regression test for https://github.com/reduxjs/redux-toolkit/issues/224', () => {
+    const oops = createAction('oops', (x: any) => ({
+      payload: x,
+      error: x,
+      meta: x,
+    }))
+
+    expectTypeOf(oops('').payload).toBeAny()
+
+    expectTypeOf(oops('').error).toBeAny()
+
+    expectTypeOf(oops('').meta).toBeAny()
+  })
+
+  describe('createAction.match()', () => {
+    test('simple use case', () => {
+      const actionCreator = createAction<string, 'test'>('test')
+
+      const x: Action<string> = {} as any
+
+      if (actionCreator.match(x)) {
+        expectTypeOf(x.type).toEqualTypeOf<'test'>()
+
+        expectTypeOf(x.payload).toBeString()
+      } else {
+        expectTypeOf(x.type).not.toMatchTypeOf<'test'>()
+
+        expectTypeOf(x).not.toHaveProperty('payload')
+      }
+    })
+
+    test('special case: optional argument', () => {
+      const actionCreator = createAction<string | undefined, 'test'>('test')
+
+      const x: Action<string> = {} as any
+
+      if (actionCreator.match(x)) {
+        expectTypeOf(x.type).toEqualTypeOf<'test'>()
+
+        expectTypeOf(x.payload).toEqualTypeOf<string | undefined>()
+      }
+    })
+
+    test('special case: without argument', () => {
+      const actionCreator = createAction('test')
+
+      const x: Action<string> = {} as any
+
+      if (actionCreator.match(x)) {
+        expectTypeOf(x.type).toEqualTypeOf<'test'>()
+
+        expectTypeOf(x.payload).not.toMatchTypeOf<{}>()
+      }
+    })
+
+    test('special case: with prepareAction', () => {
+      const actionCreator = createAction('test', () => ({
+        payload: '',
+        meta: '',
+        error: false,
+      }))
+
+      const x: Action<string> = {} as any
+
+      if (actionCreator.match(x)) {
+        expectTypeOf(x.type).toEqualTypeOf<'test'>()
+
+        expectTypeOf(x.payload).toBeString()
+
+        expectTypeOf(x.meta).toBeString()
+
+        expectTypeOf(x.error).toBeBoolean()
+
+        expectTypeOf(x.payload).not.toBeNumber()
+
+        expectTypeOf(x.meta).not.toBeNumber()
+
+        expectTypeOf(x.error).not.toBeNumber()
+      }
+    })
+    test('potential use: as array filter', () => {
+      const actionCreator = createAction<string, 'test'>('test')
+
+      const x: Action<string>[] = []
+
+      expectTypeOf(x.filter(actionCreator.match)).toEqualTypeOf<
+        PayloadAction<string, 'test'>[]
+      >()
+    })
+  })
+
+  test('ActionCreatorWithOptionalPayload', () => {
+    expectTypeOf(createAction<string | undefined>('')).toEqualTypeOf<
+      ActionCreatorWithOptionalPayload<string | undefined>
+    >()
+
+    expectTypeOf(
+      createAction<void>(''),
+    ).toEqualTypeOf<ActionCreatorWithoutPayload>()
+
+    assertType<ActionCreatorWithNonInferrablePayload>(createAction(''))
+
+    expectTypeOf(createAction<string>('')).toEqualTypeOf<
+      ActionCreatorWithPayload<string>
+    >()
+
+    expectTypeOf(
+      createAction('', (_: 0) => ({
+        payload: 1 as 1,
+        error: 2 as 2,
+        meta: 3 as 3,
+      })),
+    ).toEqualTypeOf<ActionCreatorWithPreparedPayload<[0], 1, '', 2, 3>>()
+
+    const anyCreator = createAction<any>('')
+
+    expectTypeOf(anyCreator).toEqualTypeOf<ActionCreatorWithPayload<any>>()
+
+    expectTypeOf(anyCreator({}).payload).toBeAny()
+  })
+
+  test("Verify action creators should not be passed directly as arguments to React event handlers if there shouldn't be a payload", () => {
+    const emptyAction = createAction<void>('empty/action')
+
+    function TestComponent() {
+      // This typically leads to an error like:
+      //  // A non-serializable value was detected in an action, in the path: `payload`.
+      // @ts-expect-error Should error because `void` and `MouseEvent` aren't compatible
+      return <button onClick={emptyAction}>+</button>
+    }
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/createAction.test.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/createAction.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/createAction.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,148 @@
+import { createAction, isActionCreator } from '@reduxjs/toolkit'
+
+describe('createAction', () => {
+  it('should create an action', () => {
+    const actionCreator = createAction<string>('A_TYPE')
+    expect(actionCreator('something')).toEqual({
+      type: 'A_TYPE',
+      payload: 'something',
+    })
+  })
+
+  describe('when stringifying action', () => {
+    it('should return the action type', () => {
+      const actionCreator = createAction('A_TYPE')
+      expect(`${actionCreator}`).toEqual('A_TYPE')
+    })
+  })
+
+  describe('when passing a prepareAction method only returning a payload', () => {
+    it('should use the payload returned from the prepareAction method', () => {
+      const actionCreator = createAction('A_TYPE', (a: number) => ({
+        payload: a * 2,
+      }))
+      expect(actionCreator(5).payload).toBe(10)
+    })
+    it('should not have a meta attribute on the resulting Action', () => {
+      const actionCreator = createAction('A_TYPE', (a: number) => ({
+        payload: a * 2,
+      }))
+      expect('meta' in actionCreator(5)).toBeFalsy()
+    })
+  })
+
+  describe('when passing a prepareAction method returning a payload and meta', () => {
+    it('should use the payload returned from the prepareAction method', () => {
+      const actionCreator = createAction('A_TYPE', (a: number) => ({
+        payload: a * 2,
+        meta: a / 2,
+      }))
+      expect(actionCreator(5).payload).toBe(10)
+    })
+    it('should use the meta returned from the prepareAction method', () => {
+      const actionCreator = createAction('A_TYPE', (a: number) => ({
+        payload: a * 2,
+        meta: a / 2,
+      }))
+      expect(actionCreator(10).meta).toBe(5)
+    })
+  })
+
+  describe('when passing a prepareAction method returning a payload and error', () => {
+    it('should use the payload returned from the prepareAction method', () => {
+      const actionCreator = createAction('A_TYPE', (a: number) => ({
+        payload: a * 2,
+        error: true,
+      }))
+      expect(actionCreator(5).payload).toBe(10)
+    })
+    it('should use the error returned from the prepareAction method', () => {
+      const actionCreator = createAction('A_TYPE', (a: number) => ({
+        payload: a * 2,
+        error: true,
+      }))
+      expect(actionCreator(10).error).toBe(true)
+    })
+  })
+
+  describe('when passing a prepareAction method returning a payload, meta and error', () => {
+    it('should use the payload returned from the prepareAction method', () => {
+      const actionCreator = createAction('A_TYPE', (a: number) => ({
+        payload: a * 2,
+        meta: a / 2,
+        error: true,
+      }))
+      expect(actionCreator(5).payload).toBe(10)
+    })
+    it('should use the error returned from the prepareAction method', () => {
+      const actionCreator = createAction('A_TYPE', (a: number) => ({
+        payload: a * 2,
+        meta: a / 2,
+        error: true,
+      }))
+      expect(actionCreator(10).error).toBe(true)
+    })
+    it('should use the meta returned from the prepareAction method', () => {
+      const actionCreator = createAction('A_TYPE', (a: number) => ({
+        payload: a * 2,
+        meta: a / 2,
+        error: true,
+      }))
+      expect(actionCreator(10).meta).toBe(5)
+    })
+  })
+
+  describe('when passing a prepareAction that accepts multiple arguments', () => {
+    it('should pass all arguments of the resulting actionCreator to prepareAction', () => {
+      const actionCreator = createAction(
+        'A_TYPE',
+        (a: string, b: string, c: string) => ({
+          payload: a + b + c,
+        }),
+      )
+      expect(actionCreator('1', '2', '3').payload).toBe('123')
+    })
+  })
+
+  describe('actionCreator.match', () => {
+    test('should return true for actions generated by own actionCreator', () => {
+      const actionCreator = createAction('test')
+      expect(actionCreator.match(actionCreator())).toBe(true)
+    })
+
+    test('should return true for matching actions', () => {
+      const actionCreator = createAction('test')
+      expect(actionCreator.match({ type: 'test' })).toBe(true)
+    })
+
+    test('should return false for other actions', () => {
+      const actionCreator = createAction('test')
+      expect(actionCreator.match({ type: 'test-abc' })).toBe(false)
+    })
+  })
+})
+
+const actionCreator = createAction('anAction')
+
+class Action {
+  type = 'totally an action'
+}
+
+describe('isActionCreator', () => {
+  it('should only return true for action creators', () => {
+    expect(isActionCreator(actionCreator)).toBe(true)
+    const notActionCreators = [
+      { type: 'an action' },
+      { type: 'more props', extra: true },
+      actionCreator(),
+      Promise.resolve({ type: 'an action' }),
+      new Action(),
+      false,
+      'a string',
+      false,
+    ]
+    for (const notActionCreator of notActionCreators) {
+      expect(isActionCreator(notActionCreator)).toBe(false)
+    }
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/createAsyncThunk.test-d.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/createAsyncThunk.test-d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/createAsyncThunk.test-d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,899 @@
+import type {
+  AsyncThunk,
+  SerializedError,
+  ThunkDispatch,
+  UnknownAction,
+} from '@reduxjs/toolkit'
+import {
+  configureStore,
+  createAsyncThunk,
+  createReducer,
+  createSlice,
+  unwrapResult,
+} from '@reduxjs/toolkit'
+
+import type { TSVersion } from '@phryneas/ts-version'
+import type { AxiosError } from 'axios'
+import apiRequest from 'axios'
+import type { AsyncThunkDispatchConfig } from '@internal/createAsyncThunk'
+
+const defaultDispatch = (() => {}) as ThunkDispatch<{}, any, UnknownAction>
+const unknownAction = { type: 'foo' } as UnknownAction
+
+describe('type tests', () => {
+  test('basic usage', async () => {
+    const asyncThunk = createAsyncThunk('test', (id: number) =>
+      Promise.resolve(id * 2),
+    )
+
+    const reducer = createReducer({}, (builder) =>
+      builder
+        .addCase(asyncThunk.pending, (_, action) => {
+          expectTypeOf(action).toEqualTypeOf<
+            ReturnType<(typeof asyncThunk)['pending']>
+          >()
+        })
+
+        .addCase(asyncThunk.fulfilled, (_, action) => {
+          expectTypeOf(action).toEqualTypeOf<
+            ReturnType<(typeof asyncThunk)['fulfilled']>
+          >()
+
+          expectTypeOf(action.payload).toBeNumber()
+        })
+
+        .addCase(asyncThunk.rejected, (_, action) => {
+          expectTypeOf(action).toEqualTypeOf<
+            ReturnType<(typeof asyncThunk)['rejected']>
+          >()
+
+          expectTypeOf(action.error).toMatchTypeOf<Partial<Error> | undefined>()
+        }),
+    )
+
+    const promise = defaultDispatch(asyncThunk(3))
+
+    expectTypeOf(promise.requestId).toBeString()
+
+    expectTypeOf(promise.arg).toBeNumber()
+
+    expectTypeOf(promise.abort).toEqualTypeOf<(reason?: string) => void>()
+
+    const result = await promise
+
+    if (asyncThunk.fulfilled.match(result)) {
+      expectTypeOf(result).toEqualTypeOf<
+        ReturnType<(typeof asyncThunk)['fulfilled']>
+      >()
+    } else {
+      expectTypeOf(result).toEqualTypeOf<
+        ReturnType<(typeof asyncThunk)['rejected']>
+      >()
+    }
+
+    promise
+      .then(unwrapResult)
+      .then((result) => {
+        expectTypeOf(result).toBeNumber()
+
+        expectTypeOf(result).not.toMatchTypeOf<Error>()
+      })
+      .catch((error) => {
+        // catch is always any-typed, nothing we can do here
+        expectTypeOf(error).toBeAny()
+      })
+  })
+
+  test('More complex usage of thunk args', () => {
+    interface BookModel {
+      id: string
+      title: string
+    }
+
+    type BooksState = BookModel[]
+
+    const fakeBooks: BookModel[] = [
+      { id: 'b', title: 'Second' },
+      { id: 'a', title: 'First' },
+    ]
+
+    const correctDispatch = (() => {}) as ThunkDispatch<
+      BookModel[],
+      { userAPI: Function },
+      UnknownAction
+    >
+
+    // Verify that the the first type args to createAsyncThunk line up right
+    const fetchBooksTAC = createAsyncThunk<
+      BookModel[],
+      number,
+      {
+        state: BooksState
+        extra: { userAPI: Function }
+      }
+    >(
+      'books/fetch',
+      async (arg, { getState, dispatch, extra, requestId, signal }) => {
+        const state = getState()
+
+        expectTypeOf(arg).toBeNumber()
+
+        expectTypeOf(state).toEqualTypeOf<BookModel[]>()
+
+        expectTypeOf(extra).toEqualTypeOf<{ userAPI: Function }>()
+
+        return fakeBooks
+      },
+    )
+
+    correctDispatch(fetchBooksTAC(1))
+    // @ts-expect-error
+    defaultDispatch(fetchBooksTAC(1))
+  })
+
+  test('returning a rejected action from the promise creator is possible', async () => {
+    type ReturnValue = { data: 'success' }
+    type RejectValue = { data: 'error' }
+
+    const fetchBooksTAC = createAsyncThunk<
+      ReturnValue,
+      number,
+      {
+        rejectValue: RejectValue
+      }
+    >('books/fetch', async (arg, { rejectWithValue }) => {
+      return rejectWithValue({ data: 'error' })
+    })
+
+    const returned = await defaultDispatch(fetchBooksTAC(1))
+    if (fetchBooksTAC.rejected.match(returned)) {
+      expectTypeOf(returned.payload).toEqualTypeOf<undefined | RejectValue>()
+
+      expectTypeOf(returned.payload).toBeNullable()
+    } else {
+      expectTypeOf(returned.payload).toEqualTypeOf<ReturnValue>()
+    }
+
+    expectTypeOf(unwrapResult(returned)).toEqualTypeOf<ReturnValue>()
+
+    expectTypeOf(unwrapResult(returned)).not.toMatchTypeOf<RejectValue>()
+  })
+
+  test('regression #1156: union return values fall back to allowing only single member', () => {
+    const fn = createAsyncThunk('session/isAdmin', async () => {
+      const response: boolean = false
+      return response
+    })
+  })
+
+  test('Should handle reject with value within a try catch block. Note: this is a sample code taken from #1605', () => {
+    type ResultType = {
+      text: string
+    }
+    const demoPromise = async (): Promise<ResultType> =>
+      new Promise((resolve, _) => resolve({ text: '' }))
+    const thunk = createAsyncThunk('thunk', async (args, thunkAPI) => {
+      try {
+        const result = await demoPromise()
+        return result
+      } catch (error) {
+        return thunkAPI.rejectWithValue(error)
+      }
+    })
+    createReducer({}, (builder) =>
+      builder.addCase(thunk.fulfilled, (s, action) => {
+        expectTypeOf(action.payload).toEqualTypeOf<ResultType>()
+      }),
+    )
+  })
+
+  test('reject with value', () => {
+    interface Item {
+      name: string
+    }
+
+    interface ErrorFromServer {
+      error: string
+    }
+
+    interface CallsResponse {
+      data: Item[]
+    }
+
+    const fetchLiveCallsError = createAsyncThunk<
+      Item[],
+      string,
+      {
+        rejectValue: ErrorFromServer
+      }
+    >('calls/fetchLiveCalls', async (organizationId, { rejectWithValue }) => {
+      try {
+        const result = await apiRequest.get<CallsResponse>(
+          `organizations/${organizationId}/calls/live/iwill404`,
+        )
+        return result.data.data
+      } catch (err) {
+        const error: AxiosError<ErrorFromServer> = err as any // cast for access to AxiosError properties
+        if (!error.response) {
+          // let it be handled as any other unknown error
+          throw err
+        }
+        return rejectWithValue(error.response && error.response.data)
+      }
+    })
+
+    defaultDispatch(fetchLiveCallsError('asd')).then((result) => {
+      if (fetchLiveCallsError.fulfilled.match(result)) {
+        //success
+        expectTypeOf(result).toEqualTypeOf<
+          ReturnType<(typeof fetchLiveCallsError)['fulfilled']>
+        >()
+
+        expectTypeOf(result.payload).toEqualTypeOf<Item[]>()
+      } else {
+        expectTypeOf(result).toEqualTypeOf<
+          ReturnType<(typeof fetchLiveCallsError)['rejected']>
+        >()
+
+        if (result.payload) {
+          // rejected with value
+          expectTypeOf(result.payload).toEqualTypeOf<ErrorFromServer>()
+        } else {
+          // rejected by throw
+          expectTypeOf(result.payload).toBeUndefined()
+
+          expectTypeOf(result.error).toEqualTypeOf<SerializedError>()
+
+          expectTypeOf(result.error).not.toBeAny()
+        }
+      }
+      defaultDispatch(fetchLiveCallsError('asd'))
+        .then((result) => {
+          expectTypeOf(result.payload).toEqualTypeOf<
+            Item[] | ErrorFromServer | undefined
+          >()
+
+          return result
+        })
+        .then(unwrapResult)
+        .then((unwrapped) => {
+          expectTypeOf(unwrapped).toEqualTypeOf<Item[]>()
+
+          expectTypeOf(unwrapResult).parameter(0).not.toMatchTypeOf(unwrapped)
+        })
+    })
+  })
+
+  describe('payloadCreator first argument type has impact on asyncThunk argument', () => {
+    test('asyncThunk has no argument', () => {
+      const asyncThunk = createAsyncThunk('test', () => 0)
+
+      expectTypeOf(asyncThunk).toMatchTypeOf<() => any>()
+
+      expectTypeOf(asyncThunk).parameters.toEqualTypeOf<
+        [undefined?, AsyncThunkDispatchConfig?]
+      >()
+
+      expectTypeOf(asyncThunk).returns.toBeFunction()
+    })
+
+    test('one argument, specified as undefined: asyncThunk has no argument', () => {
+      const asyncThunk = createAsyncThunk('test', (arg: undefined) => 0)
+
+      expectTypeOf(asyncThunk).toMatchTypeOf<() => any>()
+
+      expectTypeOf(asyncThunk).parameters.toEqualTypeOf<
+        [undefined?, AsyncThunkDispatchConfig?]
+      >()
+    })
+
+    test('one argument, specified as void: asyncThunk has no argument', () => {
+      const asyncThunk = createAsyncThunk('test', (arg: void) => 0)
+
+      expectTypeOf(asyncThunk).toMatchTypeOf<() => any>()
+    })
+
+    test('one argument, specified as optional number: asyncThunk has optional number argument', () => {
+      // this test will fail with strictNullChecks: false, that is to be expected
+      // in that case, we have to forbid this behavior or it will make arguments optional everywhere
+      const asyncThunk = createAsyncThunk('test', (arg?: number) => 0)
+
+      // Per https://github.com/reduxjs/redux-toolkit/issues/3758#issuecomment-1742152774 , this is a bug in
+      // TS 5.1 and 5.2, that is fixed in 5.3. Conditionally run the TS assertion here.
+      type IsTS51Or52 = TSVersion.Major extends 5
+        ? TSVersion.Minor extends 1 | 2
+          ? true
+          : false
+        : false
+
+      type expectedType = IsTS51Or52 extends true
+        ? (arg: number) => any
+        : (arg?: number) => any
+
+      expectTypeOf(asyncThunk).toMatchTypeOf<expectedType>()
+
+      // We _should_ be able to call this with no arguments, but we run into that error in 5.1 and 5.2.
+      // Disabling this for now.
+      // asyncThunk()
+      expectTypeOf(asyncThunk).toBeCallableWith(5)
+
+      expectTypeOf(asyncThunk).parameters.not.toMatchTypeOf<[string]>()
+    })
+
+    test('one argument, specified as number|undefined: asyncThunk has optional number argument', () => {
+      // this test will fail with strictNullChecks: false, that is to be expected
+      // in that case, we have to forbid this behavior or it will make arguments optional everywhere
+      const asyncThunk = createAsyncThunk(
+        'test',
+        (arg: number | undefined) => 0,
+      )
+
+      expectTypeOf(asyncThunk).toMatchTypeOf<(arg?: number) => any>()
+
+      expectTypeOf(asyncThunk).toBeCallableWith()
+
+      expectTypeOf(asyncThunk).toBeCallableWith(undefined)
+
+      expectTypeOf(asyncThunk).toBeCallableWith(5)
+
+      expectTypeOf(asyncThunk).parameters.not.toMatchTypeOf<[string]>()
+    })
+
+    test('one argument, specified as number|void: asyncThunk has optional number argument', () => {
+      const asyncThunk = createAsyncThunk('test', (arg: number | void) => 0)
+
+      expectTypeOf(asyncThunk).toMatchTypeOf<(arg?: number) => any>()
+
+      expectTypeOf(asyncThunk).toBeCallableWith()
+
+      expectTypeOf(asyncThunk).toBeCallableWith(undefined)
+
+      expectTypeOf(asyncThunk).toBeCallableWith(5)
+
+      expectTypeOf(asyncThunk).parameters.not.toMatchTypeOf<[string]>()
+    })
+
+    test('one argument, specified as any: asyncThunk has required any argument', () => {
+      const asyncThunk = createAsyncThunk('test', (arg: any) => 0)
+
+      expectTypeOf(asyncThunk).parameter(0).toBeAny()
+
+      expectTypeOf(asyncThunk).toBeCallableWith(5)
+
+      expectTypeOf(asyncThunk).parameters.not.toMatchTypeOf<[]>()
+    })
+
+    test('one argument, specified as unknown: asyncThunk has required unknown argument', () => {
+      const asyncThunk = createAsyncThunk('test', (arg: unknown) => 0)
+
+      expectTypeOf(asyncThunk).parameter(0).toBeUnknown()
+
+      expectTypeOf(asyncThunk).toBeCallableWith(5)
+
+      expectTypeOf(asyncThunk).parameters.not.toMatchTypeOf<[]>()
+    })
+
+    test('one argument, specified as number: asyncThunk has required number argument', () => {
+      const asyncThunk = createAsyncThunk('test', (arg: number) => 0)
+
+      expectTypeOf(asyncThunk).toMatchTypeOf<(arg: number) => any>()
+
+      expectTypeOf(asyncThunk).toBeCallableWith(5)
+
+      expectTypeOf(asyncThunk).parameters.not.toMatchTypeOf<[]>()
+    })
+
+    test('two arguments, first specified as undefined: asyncThunk has no argument', () => {
+      const asyncThunk = createAsyncThunk(
+        'test',
+        (arg: undefined, thunkApi) => 0,
+      )
+
+      expectTypeOf(asyncThunk).toMatchTypeOf<() => any>()
+
+      expectTypeOf(asyncThunk).toBeCallableWith()
+
+      expectTypeOf(asyncThunk).toBeCallableWith(undefined)
+
+      // cannot be called with an argument
+      expectTypeOf(asyncThunk).parameter(0).not.toBeAny()
+
+      expectTypeOf(asyncThunk).parameters.toEqualTypeOf<
+        [undefined?, AsyncThunkDispatchConfig?]
+      >()
+    })
+
+    test('two arguments, first specified as void: asyncThunk has no argument', () => {
+      const asyncThunk = createAsyncThunk('test', (arg: void, thunkApi) => 0)
+
+      expectTypeOf(asyncThunk).toMatchTypeOf<() => any>()
+
+      expectTypeOf(asyncThunk).toBeCallableWith()
+
+      expectTypeOf(asyncThunk).parameter(0).toBeVoid()
+
+      // cannot be called with an argument
+      expectTypeOf(asyncThunk).parameter(0).not.toBeAny()
+
+      expectTypeOf(asyncThunk).parameters.toEqualTypeOf<
+        [undefined?, AsyncThunkDispatchConfig?]
+      >()
+    })
+
+    test('two arguments, first specified as number|undefined: asyncThunk has optional number argument', () => {
+      // this test will fail with strictNullChecks: false, that is to be expected
+      // in that case, we have to forbid this behavior or it will make arguments optional everywhere
+      const asyncThunk = createAsyncThunk(
+        'test',
+        (arg: number | undefined, thunkApi) => 0,
+      )
+
+      expectTypeOf(asyncThunk).toMatchTypeOf<(arg?: number) => any>()
+
+      expectTypeOf(asyncThunk).toBeCallableWith()
+
+      expectTypeOf(asyncThunk).toBeCallableWith(undefined)
+
+      expectTypeOf(asyncThunk).toBeCallableWith(5)
+
+      expectTypeOf(asyncThunk).parameter(0).not.toBeString()
+    })
+
+    test('two arguments, first specified as number|void: asyncThunk has optional number argument', () => {
+      const asyncThunk = createAsyncThunk(
+        'test',
+        (arg: number | void, thunkApi) => 0,
+      )
+
+      expectTypeOf(asyncThunk).toMatchTypeOf<(arg?: number) => any>()
+
+      expectTypeOf(asyncThunk).toBeCallableWith()
+
+      expectTypeOf(asyncThunk).toBeCallableWith(undefined)
+
+      expectTypeOf(asyncThunk).toBeCallableWith(5)
+
+      expectTypeOf(asyncThunk).parameter(0).not.toBeString()
+    })
+
+    test('two arguments, first specified as any: asyncThunk has required any argument', () => {
+      const asyncThunk = createAsyncThunk('test', (arg: any, thunkApi) => 0)
+
+      expectTypeOf(asyncThunk).parameter(0).toBeAny()
+
+      expectTypeOf(asyncThunk).toBeCallableWith(5)
+
+      expectTypeOf(asyncThunk).parameters.not.toMatchTypeOf<[]>()
+    })
+
+    test('two arguments, first specified as unknown: asyncThunk has required unknown argument', () => {
+      const asyncThunk = createAsyncThunk('test', (arg: unknown, thunkApi) => 0)
+
+      expectTypeOf(asyncThunk).parameter(0).toBeUnknown()
+
+      expectTypeOf(asyncThunk).toBeCallableWith(5)
+
+      expectTypeOf(asyncThunk).parameters.not.toMatchTypeOf<[]>()
+    })
+
+    test('two arguments, first specified as number: asyncThunk has required number argument', () => {
+      const asyncThunk = createAsyncThunk('test', (arg: number, thunkApi) => 0)
+
+      expectTypeOf(asyncThunk).toMatchTypeOf<(arg: number) => any>()
+
+      expectTypeOf(asyncThunk).parameter(0).toBeNumber()
+
+      expectTypeOf(asyncThunk).toBeCallableWith(5)
+
+      expectTypeOf(asyncThunk).parameters.not.toMatchTypeOf<[]>()
+    })
+  })
+
+  test('createAsyncThunk without generics', () => {
+    const thunk = createAsyncThunk('test', () => {
+      return 'ret' as const
+    })
+
+    expectTypeOf(thunk).toEqualTypeOf<AsyncThunk<'ret', void, {}>>()
+  })
+
+  test('createAsyncThunk without generics, accessing `api` does not break return type', () => {
+    const thunk = createAsyncThunk('test', (_: void, api) => {
+      return 'ret' as const
+    })
+
+    expectTypeOf(thunk).toEqualTypeOf<AsyncThunk<'ret', void, {}>>()
+  })
+
+  test('createAsyncThunk rejectWithValue without generics: Expect correct return type', () => {
+    const asyncThunk = createAsyncThunk(
+      'test',
+      (_: void, { rejectWithValue }) => {
+        try {
+          return Promise.resolve(true)
+        } catch (e) {
+          return rejectWithValue(e)
+        }
+      },
+    )
+
+    defaultDispatch(asyncThunk())
+      .then((result) => {
+        if (asyncThunk.fulfilled.match(result)) {
+          expectTypeOf(result).toEqualTypeOf<
+            ReturnType<(typeof asyncThunk)['fulfilled']>
+          >()
+
+          expectTypeOf(result.payload).toBeBoolean()
+
+          expectTypeOf(result).not.toHaveProperty('error')
+        } else {
+          expectTypeOf(result).toEqualTypeOf<
+            ReturnType<(typeof asyncThunk)['rejected']>
+          >()
+
+          expectTypeOf(result.error).toEqualTypeOf<SerializedError>()
+
+          expectTypeOf(result.payload).toBeUnknown()
+        }
+
+        return result
+      })
+      .then(unwrapResult)
+      .then((unwrapped) => {
+        expectTypeOf(unwrapped).toBeBoolean()
+      })
+  })
+
+  test('createAsyncThunk with generics', () => {
+    type Funky = { somethingElse: 'Funky!' }
+    function funkySerializeError(err: any): Funky {
+      return { somethingElse: 'Funky!' }
+    }
+
+    // has to stay on one line or type tests fail in older TS versions
+    // prettier-ignore
+    // @ts-expect-error
+    const shouldFail = createAsyncThunk('without generics', () => {}, { serializeError: funkySerializeError })
+
+    const shouldWork = createAsyncThunk<
+      any,
+      void,
+      { serializedErrorType: Funky }
+    >('with generics', () => {}, {
+      serializeError: funkySerializeError,
+    })
+
+    if (shouldWork.rejected.match(unknownAction)) {
+      expectTypeOf(unknownAction.error).toEqualTypeOf<Funky>()
+    }
+  })
+
+  test('`idGenerator` option takes no arguments, and returns a string', () => {
+    const returnsNumWithArgs = (foo: any) => 100
+    // has to stay on one line or type tests fail in older TS versions
+    // prettier-ignore
+    // @ts-expect-error
+    const shouldFailNumWithArgs = createAsyncThunk('foo', () => {}, { idGenerator: returnsNumWithArgs })
+
+    const returnsNumWithoutArgs = () => 100
+    // prettier-ignore
+    // @ts-expect-error
+    const shouldFailNumWithoutArgs = createAsyncThunk('foo', () => {}, { idGenerator: returnsNumWithoutArgs })
+
+    const returnsStrWithNumberArg = (foo: number) => 'foo'
+    // prettier-ignore
+    // @ts-expect-error
+    const shouldFailWrongArgs = createAsyncThunk('foo', (arg: string) => {}, { idGenerator: returnsStrWithNumberArg })
+
+    const returnsStrWithStringArg = (foo: string) => 'foo'
+    const shoulducceedCorrectArgs = createAsyncThunk(
+      'foo',
+      (arg: string) => {},
+      {
+        idGenerator: returnsStrWithStringArg,
+      },
+    )
+
+    const returnsStrWithoutArgs = () => 'foo'
+    const shouldSucceed = createAsyncThunk('foo', () => {}, {
+      idGenerator: returnsStrWithoutArgs,
+    })
+  })
+
+  test('fulfillWithValue should infer return value', () => {
+    // https://github.com/reduxjs/redux-toolkit/issues/2886
+
+    const initialState = {
+      loading: false,
+      obj: { magic: '' },
+    }
+
+    const getObj = createAsyncThunk(
+      'slice/getObj',
+      async (_: any, { fulfillWithValue, rejectWithValue }) => {
+        try {
+          return fulfillWithValue({ magic: 'object' })
+        } catch (rejected: any) {
+          return rejectWithValue(rejected?.response?.error || rejected)
+        }
+      },
+    )
+
+    createSlice({
+      name: 'slice',
+      initialState,
+      reducers: {},
+      extraReducers: (builder) => {
+        builder.addCase(getObj.fulfilled, (state, action) => {
+          expectTypeOf(action.payload).toEqualTypeOf<{ magic: string }>()
+        })
+      },
+    })
+  })
+
+  test('meta return values', () => {
+    // return values
+    createAsyncThunk<'ret', void, {}>('test', (_, api) => 'ret' as const)
+    createAsyncThunk<'ret', void, {}>('test', async (_, api) => 'ret' as const)
+    createAsyncThunk<'ret', void, { fulfilledMeta: string }>('test', (_, api) =>
+      api.fulfillWithValue('ret' as const, ''),
+    )
+    createAsyncThunk<'ret', void, { fulfilledMeta: string }>(
+      'test',
+      async (_, api) => api.fulfillWithValue('ret' as const, ''),
+    )
+    createAsyncThunk<'ret', void, { fulfilledMeta: string }>(
+      'test',
+      // @ts-expect-error has to be a fulfilledWithValue call
+      (_, api) => 'ret' as const,
+    )
+    createAsyncThunk<'ret', void, { fulfilledMeta: string }>(
+      'test',
+      // @ts-expect-error has to be a fulfilledWithValue call
+      async (_, api) => 'ret' as const,
+    )
+    createAsyncThunk<'ret', void, { fulfilledMeta: string }>(
+      'test', // @ts-expect-error should only allow returning with 'test'
+      (_, api) => api.fulfillWithValue(5, ''),
+    )
+    createAsyncThunk<'ret', void, { fulfilledMeta: string }>(
+      'test', // @ts-expect-error should only allow returning with 'test'
+      async (_, api) => api.fulfillWithValue(5, ''),
+    )
+
+    // reject values
+    createAsyncThunk<'ret', void, { rejectValue: string }>('test', (_, api) =>
+      api.rejectWithValue('ret'),
+    )
+    createAsyncThunk<'ret', void, { rejectValue: string }>(
+      'test',
+      async (_, api) => api.rejectWithValue('ret'),
+    )
+    createAsyncThunk<
+      'ret',
+      void,
+      { rejectValue: string; rejectedMeta: number }
+    >('test', (_, api) => api.rejectWithValue('ret', 5))
+    createAsyncThunk<
+      'ret',
+      void,
+      { rejectValue: string; rejectedMeta: number }
+    >('test', async (_, api) => api.rejectWithValue('ret', 5))
+    createAsyncThunk<
+      'ret',
+      void,
+      { rejectValue: string; rejectedMeta: number }
+    >('test', (_, api) => api.rejectWithValue('ret', 5))
+    createAsyncThunk<
+      'ret',
+      void,
+      { rejectValue: string; rejectedMeta: number }
+    >(
+      'test',
+      // @ts-expect-error wrong rejectedMeta type
+      (_, api) => api.rejectWithValue('ret', ''),
+    )
+    createAsyncThunk<
+      'ret',
+      void,
+      { rejectValue: string; rejectedMeta: number }
+    >(
+      'test',
+      // @ts-expect-error wrong rejectedMeta type
+      async (_, api) => api.rejectWithValue('ret', ''),
+    )
+    createAsyncThunk<
+      'ret',
+      void,
+      { rejectValue: string; rejectedMeta: number }
+    >(
+      'test',
+      // @ts-expect-error wrong rejectValue type
+      (_, api) => api.rejectWithValue(5, ''),
+    )
+    createAsyncThunk<
+      'ret',
+      void,
+      { rejectValue: string; rejectedMeta: number }
+    >(
+      'test',
+      // @ts-expect-error wrong rejectValue type
+      async (_, api) => api.rejectWithValue(5, ''),
+    )
+  })
+
+  test('usage with config override generic', () => {
+    const typedCAT = createAsyncThunk.withTypes<{
+      state: RootState
+      dispatch: AppDispatch
+      rejectValue: string
+      extra: { s: string; n: number }
+    }>()
+
+    // inferred usage
+    const thunk = typedCAT('foo', (arg: number, api) => {
+      // correct getState Type
+      const test1: number = api.getState().foo.value
+      // correct dispatch type
+      const test2: number = api.dispatch((dispatch, getState) => {
+        expectTypeOf(dispatch).toEqualTypeOf<
+          ThunkDispatch<{ foo: { value: number } }, undefined, UnknownAction>
+        >()
+
+        expectTypeOf(getState).toEqualTypeOf<() => { foo: { value: number } }>()
+
+        return getState().foo.value
+      })
+
+      // correct extra type
+      const { s, n } = api.extra
+
+      expectTypeOf(s).toBeString()
+
+      expectTypeOf(n).toBeNumber()
+
+      if (1 < 2)
+        // @ts-expect-error
+        return api.rejectWithValue(5)
+      if (1 < 2) return api.rejectWithValue('test')
+      return test1 + test2
+    })
+
+    // usage with two generics
+    const thunk2 = typedCAT<number, string>('foo', (arg, api) => {
+      expectTypeOf(arg).toBeString()
+
+      // correct getState Type
+      const test1: number = api.getState().foo.value
+      // correct dispatch type
+      const test2: number = api.dispatch((dispatch, getState) => {
+        expectTypeOf(dispatch).toEqualTypeOf<
+          ThunkDispatch<{ foo: { value: number } }, undefined, UnknownAction>
+        >()
+
+        expectTypeOf(getState).toEqualTypeOf<() => { foo: { value: number } }>()
+
+        return getState().foo.value
+      })
+      // correct extra type
+      const { s, n } = api.extra
+
+      expectTypeOf(s).toBeString()
+
+      expectTypeOf(n).toBeNumber()
+
+      if (1 < 2) expectTypeOf(api.rejectWithValue).toBeCallableWith('test')
+
+      expectTypeOf(api.rejectWithValue).parameter(0).not.toBeNumber()
+
+      expectTypeOf(api.rejectWithValue).parameters.toEqualTypeOf<[string]>()
+
+      return api.rejectWithValue('test')
+    })
+
+    // usage with config override generic
+    const thunk3 = typedCAT<number, string, { rejectValue: number }>(
+      'foo',
+      (arg, api) => {
+        expectTypeOf(arg).toBeString()
+
+        // correct getState Type
+        const test1: number = api.getState().foo.value
+        // correct dispatch type
+        const test2: number = api.dispatch((dispatch, getState) => {
+          expectTypeOf(dispatch).toEqualTypeOf<
+            ThunkDispatch<{ foo: { value: number } }, undefined, UnknownAction>
+          >()
+
+          expectTypeOf(getState).toEqualTypeOf<
+            () => { foo: { value: number } }
+          >()
+
+          return getState().foo.value
+        })
+        // correct extra type
+        const { s, n } = api.extra
+
+        expectTypeOf(s).toBeString()
+
+        expectTypeOf(n).toBeNumber()
+
+        if (1 < 2) return api.rejectWithValue(5)
+        if (1 < 2) expectTypeOf(api.rejectWithValue).toBeCallableWith(5)
+
+        expectTypeOf(api.rejectWithValue).parameter(0).not.toBeString()
+
+        expectTypeOf(api.rejectWithValue).parameters.toEqualTypeOf<[number]>()
+
+        return api.rejectWithValue(5)
+      },
+    )
+
+    const slice = createSlice({
+      name: 'foo',
+      initialState: { value: 0 },
+      reducers: {},
+      extraReducers(builder) {
+        builder
+          .addCase(thunk.fulfilled, (state, action) => {
+            state.value += action.payload
+          })
+          .addCase(thunk.rejected, (state, action) => {
+            expectTypeOf(action.payload).toEqualTypeOf<string | undefined>()
+          })
+          .addCase(thunk2.fulfilled, (state, action) => {
+            state.value += action.payload
+          })
+          .addCase(thunk2.rejected, (state, action) => {
+            expectTypeOf(action.payload).toEqualTypeOf<string | undefined>()
+          })
+          .addCase(thunk3.fulfilled, (state, action) => {
+            state.value += action.payload
+          })
+          .addCase(thunk3.rejected, (state, action) => {
+            expectTypeOf(action.payload).toEqualTypeOf<number | undefined>()
+          })
+      },
+    })
+
+    const store = configureStore({
+      reducer: {
+        foo: slice.reducer,
+      },
+    })
+
+    type RootState = ReturnType<typeof store.getState>
+    type AppDispatch = typeof store.dispatch
+  })
+
+  test('rejectedMeta', async () => {
+    const getNewStore = () =>
+      configureStore({
+        reducer(actions = [], action) {
+          return [...actions, action]
+        },
+      })
+
+    const store = getNewStore()
+
+    const fulfilledThunk = createAsyncThunk<
+      string,
+      string,
+      { rejectedMeta: { extraProp: string } }
+    >('test', (arg: string, { rejectWithValue }) => {
+      return rejectWithValue('damn!', { extraProp: 'baz' })
+    })
+
+    const promise = store.dispatch(fulfilledThunk('testArg'))
+
+    const ret = await promise
+
+    if (ret.meta.requestStatus === 'rejected' && ret.meta.rejectedWithValue) {
+      expectTypeOf(ret.meta.extraProp).toBeString()
+    } else {
+      // could be caused by a `throw`, `abort()` or `condition` - no `rejectedMeta` in that case
+      expectTypeOf(ret.meta).not.toHaveProperty('extraProp')
+    }
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/createAsyncThunk.test.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/createAsyncThunk.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/createAsyncThunk.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,1045 @@
+import { noop } from '@internal/listenerMiddleware/utils'
+import { delay, promiseWithResolvers } from '@internal/utils'
+import type { CreateAsyncThunkFunction, UnknownAction } from '@reduxjs/toolkit'
+import {
+  configureStore,
+  createAsyncThunk,
+  createReducer,
+  miniSerializeError,
+  unwrapResult,
+} from '@reduxjs/toolkit'
+
+declare global {
+  interface Window {
+    AbortController: AbortController
+  }
+}
+
+describe('createAsyncThunk', () => {
+  it('creates the action types', () => {
+    const thunkActionCreator = createAsyncThunk('testType', async () => 42)
+
+    expect(thunkActionCreator.fulfilled.type).toBe('testType/fulfilled')
+    expect(thunkActionCreator.pending.type).toBe('testType/pending')
+    expect(thunkActionCreator.rejected.type).toBe('testType/rejected')
+  })
+
+  it('exposes the typePrefix it was created with', () => {
+    const thunkActionCreator = createAsyncThunk('testType', async () => 42)
+
+    expect(thunkActionCreator.typePrefix).toBe('testType')
+  })
+
+  it('includes a settled matcher', () => {
+    const thunkActionCreator = createAsyncThunk('testType', async () => 42)
+    expect(thunkActionCreator.settled).toEqual(expect.any(Function))
+    expect(thunkActionCreator.settled(thunkActionCreator.pending(''))).toBe(
+      false,
+    )
+    expect(
+      thunkActionCreator.settled(thunkActionCreator.rejected(null, '')),
+    ).toBe(true)
+    expect(
+      thunkActionCreator.settled(thunkActionCreator.fulfilled(42, '')),
+    ).toBe(true)
+  })
+
+  it('works without passing arguments to the payload creator', async () => {
+    const thunkActionCreator = createAsyncThunk('testType', async () => 42)
+
+    let timesReducerCalled = 0
+
+    const reducer = () => {
+      timesReducerCalled++
+    }
+
+    const store = configureStore({
+      reducer,
+    })
+
+    // reset from however many times the store called it
+    timesReducerCalled = 0
+
+    await store.dispatch(thunkActionCreator())
+
+    expect(timesReducerCalled).toBe(2)
+  })
+
+  it('accepts arguments and dispatches the actions on resolve', async () => {
+    const dispatch = vi.fn()
+
+    let passedArg: any
+
+    const result = 42
+    const args = 123
+    let generatedRequestId = ''
+
+    const thunkActionCreator = createAsyncThunk(
+      'testType',
+      async (arg: number, { requestId }) => {
+        passedArg = arg
+        generatedRequestId = requestId
+        return result
+      },
+    )
+
+    const thunkFunction = thunkActionCreator(args)
+
+    const thunkPromise = thunkFunction(dispatch, () => {}, undefined)
+
+    expect(thunkPromise.requestId).toBe(generatedRequestId)
+    expect(thunkPromise.arg).toBe(args)
+
+    await thunkPromise
+
+    expect(passedArg).toBe(args)
+
+    expect(dispatch).toHaveBeenNthCalledWith(
+      1,
+      thunkActionCreator.pending(generatedRequestId, args),
+    )
+
+    expect(dispatch).toHaveBeenNthCalledWith(
+      2,
+      thunkActionCreator.fulfilled(result, generatedRequestId, args),
+    )
+  })
+
+  it('accepts arguments and dispatches the actions on reject', async () => {
+    const dispatch = vi.fn()
+
+    const args = 123
+    let generatedRequestId = ''
+
+    const error = new Error('Panic!')
+
+    const thunkActionCreator = createAsyncThunk(
+      'testType',
+      async (args: number, { requestId }) => {
+        generatedRequestId = requestId
+        throw error
+      },
+    )
+
+    const thunkFunction = thunkActionCreator(args)
+
+    try {
+      await thunkFunction(dispatch, () => {}, undefined)
+    } catch (e) {}
+
+    expect(dispatch).toHaveBeenNthCalledWith(
+      1,
+      thunkActionCreator.pending(generatedRequestId, args),
+    )
+
+    expect(dispatch).toHaveBeenCalledTimes(2)
+
+    // Have to check the bits of the action separately since the error was processed
+    const errorAction = dispatch.mock.calls[1][0]
+    expect(errorAction.error).toEqual(miniSerializeError(error))
+    expect(errorAction.meta.requestId).toBe(generatedRequestId)
+    expect(errorAction.meta.arg).toBe(args)
+  })
+
+  it('dispatches an empty error when throwing a random object without serializedError properties', async () => {
+    const dispatch = vi.fn()
+
+    const args = 123
+    let generatedRequestId = ''
+
+    const errorObject = { wny: 'dothis' }
+
+    const thunkActionCreator = createAsyncThunk(
+      'testType',
+      async (args: number, { requestId }) => {
+        generatedRequestId = requestId
+        throw errorObject
+      },
+    )
+
+    const thunkFunction = thunkActionCreator(args)
+
+    try {
+      await thunkFunction(dispatch, () => {}, undefined)
+    } catch (e) {}
+
+    expect(dispatch).toHaveBeenNthCalledWith(
+      1,
+      thunkActionCreator.pending(generatedRequestId, args),
+    )
+
+    expect(dispatch).toHaveBeenCalledTimes(2)
+
+    const errorAction = dispatch.mock.calls[1][0]
+    expect(errorAction.error).toEqual({})
+    expect(errorAction.meta.requestId).toBe(generatedRequestId)
+    expect(errorAction.meta.arg).toBe(args)
+  })
+
+  it('dispatches an action with a formatted error when throwing an object with known error keys', async () => {
+    const dispatch = vi.fn()
+
+    const args = 123
+    let generatedRequestId = ''
+
+    const errorObject = {
+      name: 'Custom thrown error',
+      message: 'This is not necessary',
+      code: '400',
+    }
+
+    const thunkActionCreator = createAsyncThunk(
+      'testType',
+      async (args: number, { requestId }) => {
+        generatedRequestId = requestId
+        throw errorObject
+      },
+    )
+
+    const thunkFunction = thunkActionCreator(args)
+
+    try {
+      await thunkFunction(dispatch, () => {}, undefined)
+    } catch (e) {}
+
+    expect(dispatch).toHaveBeenNthCalledWith(
+      1,
+      thunkActionCreator.pending(generatedRequestId, args),
+    )
+
+    expect(dispatch).toHaveBeenCalledTimes(2)
+
+    // Have to check the bits of the action separately since the error was processed
+    const errorAction = dispatch.mock.calls[1][0]
+    expect(errorAction.error).toEqual(miniSerializeError(errorObject))
+    expect(Object.keys(errorAction.error)).not.toContain('stack')
+    expect(errorAction.meta.requestId).toBe(generatedRequestId)
+    expect(errorAction.meta.arg).toBe(args)
+  })
+
+  it('dispatches a rejected action with a customized payload when a user returns rejectWithValue()', async () => {
+    const dispatch = vi.fn()
+
+    const args = 123
+    let generatedRequestId = ''
+
+    const errorPayload = {
+      errorMessage:
+        'I am a fake server-provided 400 payload with validation details',
+      errors: [
+        { field_one: 'Must be a string' },
+        { field_two: 'Must be a number' },
+      ],
+    }
+
+    const thunkActionCreator = createAsyncThunk(
+      'testType',
+      async (args: number, { requestId, rejectWithValue }) => {
+        generatedRequestId = requestId
+
+        return rejectWithValue(errorPayload)
+      },
+    )
+
+    const thunkFunction = thunkActionCreator(args)
+
+    try {
+      await thunkFunction(dispatch, () => {}, undefined)
+    } catch (e) {}
+
+    expect(dispatch).toHaveBeenNthCalledWith(
+      1,
+      thunkActionCreator.pending(generatedRequestId, args),
+    )
+
+    expect(dispatch).toHaveBeenCalledTimes(2)
+
+    // Have to check the bits of the action separately since the error was processed
+    const errorAction = dispatch.mock.calls[1][0]
+
+    expect(errorAction.error.message).toEqual('Rejected')
+    expect(errorAction.payload).toBe(errorPayload)
+    expect(errorAction.meta.arg).toBe(args)
+  })
+
+  it('dispatches a rejected action with a customized payload when a user throws rejectWithValue()', async () => {
+    const dispatch = vi.fn()
+
+    const args = 123
+    let generatedRequestId = ''
+
+    const errorPayload = {
+      errorMessage:
+        'I am a fake server-provided 400 payload with validation details',
+      errors: [
+        { field_one: 'Must be a string' },
+        { field_two: 'Must be a number' },
+      ],
+    }
+
+    const thunkActionCreator = createAsyncThunk(
+      'testType',
+      async (args: number, { requestId, rejectWithValue }) => {
+        generatedRequestId = requestId
+
+        throw rejectWithValue(errorPayload)
+      },
+    )
+
+    const thunkFunction = thunkActionCreator(args)
+
+    try {
+      await thunkFunction(dispatch, () => {}, undefined)
+    } catch (e) {}
+
+    expect(dispatch).toHaveBeenNthCalledWith(
+      1,
+      thunkActionCreator.pending(generatedRequestId, args),
+    )
+
+    expect(dispatch).toHaveBeenCalledTimes(2)
+
+    // Have to check the bits of the action separately since the error was processed
+    const errorAction = dispatch.mock.calls[1][0]
+
+    expect(errorAction.error.message).toEqual('Rejected')
+    expect(errorAction.payload).toBe(errorPayload)
+    expect(errorAction.meta.arg).toBe(args)
+  })
+
+  it('dispatches a rejected action with a miniSerializeError when rejectWithValue conditions are not satisfied', async () => {
+    const dispatch = vi.fn()
+
+    const args = 123
+    let generatedRequestId = ''
+
+    const error = new Error('Panic!')
+
+    const errorPayload = {
+      errorMessage:
+        'I am a fake server-provided 400 payload with validation details',
+      errors: [
+        { field_one: 'Must be a string' },
+        { field_two: 'Must be a number' },
+      ],
+    }
+
+    const thunkActionCreator = createAsyncThunk(
+      'testType',
+      async (args: number, { requestId, rejectWithValue }) => {
+        generatedRequestId = requestId
+
+        try {
+          throw error
+        } catch (err) {
+          if (!(err as any).response) {
+            throw err
+          }
+          return rejectWithValue(errorPayload)
+        }
+      },
+    )
+
+    const thunkFunction = thunkActionCreator(args)
+
+    try {
+      await thunkFunction(dispatch, () => {}, undefined)
+    } catch (e) {}
+
+    expect(dispatch).toHaveBeenNthCalledWith(
+      1,
+      thunkActionCreator.pending(generatedRequestId, args),
+    )
+
+    expect(dispatch).toHaveBeenCalledTimes(2)
+
+    // Have to check the bits of the action separately since the error was processed
+    const errorAction = dispatch.mock.calls[1][0]
+    expect(errorAction.error).toEqual(miniSerializeError(error))
+    expect(errorAction.payload).toEqual(undefined)
+    expect(errorAction.meta.requestId).toBe(generatedRequestId)
+    expect(errorAction.meta.arg).toBe(args)
+  })
+})
+
+describe('createAsyncThunk with abortController', () => {
+  const asyncThunk = createAsyncThunk(
+    'test',
+    function abortablePayloadCreator(_: any, { signal }) {
+      return new Promise((resolve, reject) => {
+        if (signal.aborted) {
+          reject(
+            new DOMException(
+              'This should never be reached as it should already be handled.',
+              'AbortError',
+            ),
+          )
+        }
+        signal.addEventListener('abort', () => {
+          reject(new DOMException('Was aborted while running', 'AbortError'))
+        })
+        setTimeout(resolve, 100)
+      })
+    },
+  )
+
+  let store = configureStore({
+    reducer(store: UnknownAction[] = []) {
+      return store
+    },
+  })
+
+  beforeEach(() => {
+    store = configureStore({
+      reducer(store: UnknownAction[] = [], action) {
+        return [...store, action]
+      },
+    })
+  })
+
+  test('normal usage', async () => {
+    await store.dispatch(asyncThunk({}))
+    expect(store.getState()).toEqual([
+      expect.any(Object),
+      expect.objectContaining({ type: 'test/pending' }),
+      expect.objectContaining({ type: 'test/fulfilled' }),
+    ])
+  })
+
+  test('abort after dispatch', async () => {
+    const promise = store.dispatch(asyncThunk({}))
+    promise.abort('AbortReason')
+    const result = await promise
+    const expectedAbortedAction = {
+      type: 'test/rejected',
+      error: {
+        message: 'AbortReason',
+        name: 'AbortError',
+      },
+      meta: { aborted: true, requestId: promise.requestId },
+    }
+
+    // abortedAction with reason is dispatched after test/pending is dispatched
+    expect(store.getState()).toMatchObject([
+      {},
+      { type: 'test/pending' },
+      expectedAbortedAction,
+    ])
+
+    // same abortedAction is returned, but with the AbortError from the abortablePayloadCreator
+    expect(result).toMatchObject(expectedAbortedAction)
+
+    // calling unwrapResult on the returned object re-throws the error from the abortablePayloadCreator
+    expect(() => unwrapResult(result)).toThrowError(
+      expect.objectContaining(expectedAbortedAction.error),
+    )
+  })
+
+  test('even when the payloadCreator does not directly support the signal, no further actions are dispatched', async () => {
+    const unawareAsyncThunk = createAsyncThunk('unaware', async () => {
+      await new Promise((resolve) => setTimeout(resolve, 100))
+      return 'finished'
+    })
+
+    const promise = store.dispatch(unawareAsyncThunk())
+    promise.abort('AbortReason')
+    const result = await promise
+
+    const expectedAbortedAction = {
+      type: 'unaware/rejected',
+      error: {
+        message: 'AbortReason',
+        name: 'AbortError',
+      },
+    }
+
+    // abortedAction with reason is dispatched after test/pending is dispatched
+    expect(store.getState()).toEqual([
+      expect.any(Object),
+      expect.objectContaining({ type: 'unaware/pending' }),
+      expect.objectContaining(expectedAbortedAction),
+    ])
+
+    // same abortedAction is returned, but with the AbortError from the abortablePayloadCreator
+    expect(result).toMatchObject(expectedAbortedAction)
+
+    // calling unwrapResult on the returned object re-throws the error from the abortablePayloadCreator
+    expect(() => unwrapResult(result)).toThrowError(
+      expect.objectContaining(expectedAbortedAction.error),
+    )
+  })
+
+  test('dispatch(asyncThunk) returns on abort and does not wait for the promiseProvider to finish', async () => {
+    let running = false
+    const longRunningAsyncThunk = createAsyncThunk('longRunning', async () => {
+      running = true
+      await new Promise((resolve) => setTimeout(resolve, 30000))
+      running = false
+    })
+
+    const promise = store.dispatch(longRunningAsyncThunk())
+    expect(running).toBeTruthy()
+    promise.abort()
+    const result = await promise
+    expect(running).toBeTruthy()
+    expect(result).toMatchObject({
+      type: 'longRunning/rejected',
+      error: { message: 'Aborted', name: 'AbortError' },
+      meta: { aborted: true },
+    })
+  })
+
+  describe('behavior with missing AbortController', () => {
+    let keepAbortController: (typeof window)['AbortController']
+    let freshlyLoadedModule: typeof import('../createAsyncThunk')
+
+    beforeEach(async () => {
+      keepAbortController = window.AbortController
+      delete (window as any).AbortController
+      vi.resetModules()
+      freshlyLoadedModule = await import('../createAsyncThunk')
+      vi.stubEnv('NODE_ENV', 'development')
+    })
+
+    afterEach(() => {
+      vi.unstubAllEnvs()
+      vi.clearAllMocks()
+      vi.stubGlobal('AbortController', keepAbortController)
+      vi.resetModules()
+    })
+
+    test('calling a thunk made with createAsyncThunk should fail if no global abortController is not available', async () => {
+      const longRunningAsyncThunk = freshlyLoadedModule.createAsyncThunk(
+        'longRunning',
+        async () => {
+          await new Promise((resolve) => setTimeout(resolve, 30000))
+        },
+      )
+
+      expect(longRunningAsyncThunk()).toThrow('AbortController is not defined')
+    })
+  })
+})
+
+test('non-serializable arguments are ignored by serializableStateInvariantMiddleware', async () => {
+  const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(noop)
+  const nonSerializableValue = new Map()
+  const asyncThunk = createAsyncThunk('test', (arg: Map<any, any>) => {})
+
+  configureStore({
+    reducer: () => 0,
+  }).dispatch(asyncThunk(nonSerializableValue))
+
+  expect(consoleErrorSpy).not.toHaveBeenCalled()
+
+  consoleErrorSpy.mockRestore()
+})
+
+describe('conditional skipping of asyncThunks', () => {
+  const arg = {}
+  const getState = vi.fn(() => ({}))
+  const dispatch = vi.fn((x: any) => x)
+  const payloadCreator = vi.fn((x: typeof arg) => 10)
+  const condition = vi.fn(() => false)
+  const extra = {}
+
+  beforeEach(() => {
+    getState.mockClear()
+    dispatch.mockClear()
+    payloadCreator.mockClear()
+    condition.mockClear()
+  })
+
+  test('returning false from condition skips payloadCreator and returns a rejected action', async () => {
+    const asyncThunk = createAsyncThunk('test', payloadCreator, { condition })
+    const result = await asyncThunk(arg)(dispatch, getState, extra)
+
+    expect(condition).toHaveBeenCalled()
+    expect(payloadCreator).not.toHaveBeenCalled()
+    expect(asyncThunk.rejected.match(result)).toBe(true)
+    expect((result as any).meta.condition).toBe(true)
+  })
+
+  test('return falsy from condition does not skip payload creator', async () => {
+    // Override TS's expectation that this is a boolean
+    condition.mockReturnValueOnce(undefined as unknown as boolean)
+    const asyncThunk = createAsyncThunk('test', payloadCreator, { condition })
+    const result = await asyncThunk(arg)(dispatch, getState, extra)
+
+    expect(condition).toHaveBeenCalled()
+    expect(payloadCreator).toHaveBeenCalled()
+    expect(asyncThunk.fulfilled.match(result)).toBe(true)
+    expect(result.payload).toBe(10)
+  })
+
+  test('returning true from condition executes payloadCreator', async () => {
+    condition.mockReturnValueOnce(true)
+    const asyncThunk = createAsyncThunk('test', payloadCreator, { condition })
+    const result = await asyncThunk(arg)(dispatch, getState, extra)
+
+    expect(condition).toHaveBeenCalled()
+    expect(payloadCreator).toHaveBeenCalled()
+    expect(asyncThunk.fulfilled.match(result)).toBe(true)
+    expect(result.payload).toBe(10)
+  })
+
+  test('condition is called with arg, getState and extra', async () => {
+    const asyncThunk = createAsyncThunk('test', payloadCreator, { condition })
+    await asyncThunk(arg)(dispatch, getState, extra)
+
+    expect(condition).toHaveBeenCalledOnce()
+    expect(condition).toHaveBeenLastCalledWith(
+      arg,
+      expect.objectContaining({ getState, extra }),
+    )
+  })
+
+  test('pending is dispatched synchronously if condition is synchronous', async () => {
+    const condition = () => true
+    const asyncThunk = createAsyncThunk('test', payloadCreator, { condition })
+    const thunkCallPromise = asyncThunk(arg)(dispatch, getState, extra)
+    expect(dispatch).toHaveBeenCalledOnce()
+    await thunkCallPromise
+    expect(dispatch).toHaveBeenCalledTimes(2)
+  })
+
+  test('async condition', async () => {
+    const condition = () => Promise.resolve(false)
+    const asyncThunk = createAsyncThunk('test', payloadCreator, { condition })
+    await asyncThunk(arg)(dispatch, getState, extra)
+    expect(dispatch).not.toHaveBeenCalled()
+  })
+
+  test('async condition with rejected promise', async () => {
+    const condition = () => Promise.reject()
+    const asyncThunk = createAsyncThunk('test', payloadCreator, { condition })
+    await asyncThunk(arg)(dispatch, getState, extra)
+    expect(dispatch).toHaveBeenCalledOnce()
+    expect(dispatch).toHaveBeenLastCalledWith(
+      expect.objectContaining({ type: 'test/rejected' }),
+    )
+  })
+
+  test('async condition with AbortController signal first', async () => {
+    const condition = async () => {
+      await delay(25)
+      return true
+    }
+    const asyncThunk = createAsyncThunk('test', payloadCreator, { condition })
+
+    try {
+      const thunkPromise = asyncThunk(arg)(dispatch, getState, extra)
+      thunkPromise.abort()
+      await thunkPromise
+    } catch (err) {}
+    expect(dispatch).not.toHaveBeenCalled()
+  })
+
+  test('rejected action is not dispatched by default', async () => {
+    const asyncThunk = createAsyncThunk('test', payloadCreator, { condition })
+    await asyncThunk(arg)(dispatch, getState, extra)
+
+    expect(dispatch).not.toHaveBeenCalled()
+  })
+
+  test('does not fail when attempting to abort a canceled promise', async () => {
+    const asyncPayloadCreator = vi.fn(async (x: typeof arg) => {
+      await delay(200)
+      return 10
+    })
+
+    const asyncThunk = createAsyncThunk('test', asyncPayloadCreator, {
+      condition,
+    })
+    const promise = asyncThunk(arg)(dispatch, getState, extra)
+    promise.abort(
+      `If the promise was 1. somehow canceled, 2. in a 'started' state and 3. we attempted to abort, this would crash the tests`,
+    )
+  })
+
+  test('rejected action can be dispatched via option', async () => {
+    const asyncThunk = createAsyncThunk('test', payloadCreator, {
+      condition,
+      dispatchConditionRejection: true,
+    })
+    await asyncThunk(arg)(dispatch, getState, extra)
+
+    expect(dispatch).toHaveBeenCalledOnce()
+    expect(dispatch).toHaveBeenLastCalledWith(
+      expect.objectContaining({
+        error: {
+          message: 'Aborted due to condition callback returning false.',
+          name: 'ConditionError',
+        },
+        meta: {
+          aborted: false,
+          arg,
+          rejectedWithValue: false,
+          condition: true,
+          requestId: expect.stringContaining(''),
+          requestStatus: 'rejected',
+        },
+        payload: undefined,
+        type: 'test/rejected',
+      }),
+    )
+  })
+})
+
+test('serializeError implementation', async () => {
+  function serializeError() {
+    return 'serialized!'
+  }
+  const errorObject = 'something else!'
+
+  const store = configureStore({
+    reducer: (state = [], action) => [...state, action],
+  })
+
+  const asyncThunk = createAsyncThunk<
+    unknown,
+    void,
+    { serializedErrorType: string }
+  >('test', () => Promise.reject(errorObject), { serializeError })
+  const rejected = await store.dispatch(asyncThunk())
+  if (!asyncThunk.rejected.match(rejected)) {
+    throw new Error()
+  }
+
+  const expectation = {
+    type: 'test/rejected',
+    payload: undefined,
+    error: 'serialized!',
+    meta: expect.any(Object),
+  }
+  expect(rejected).toEqual(expectation)
+  expect(store.getState()[2]).toEqual(expectation)
+  expect(rejected.error).not.toEqual(miniSerializeError(errorObject))
+})
+
+describe('unwrapResult', () => {
+  const getState = vi.fn(() => ({}))
+  const dispatch = vi.fn((x: any) => x)
+  const extra = {}
+  test('fulfilled case', async () => {
+    const asyncThunk = createAsyncThunk('test', () => {
+      return 'fulfilled!' as const
+    })
+
+    const unwrapPromise = asyncThunk()(dispatch, getState, extra).then(
+      unwrapResult,
+    )
+
+    await expect(unwrapPromise).resolves.toBe('fulfilled!')
+
+    const unwrapPromise2 = asyncThunk()(dispatch, getState, extra)
+    const res = await unwrapPromise2.unwrap()
+    expect(res).toBe('fulfilled!')
+  })
+  test('error case', async () => {
+    const error = new Error('Panic!')
+    const asyncThunk = createAsyncThunk('test', () => {
+      throw error
+    })
+
+    const unwrapPromise = asyncThunk()(dispatch, getState, extra).then(
+      unwrapResult,
+    )
+
+    await expect(unwrapPromise).rejects.toEqual(miniSerializeError(error))
+
+    const unwrapPromise2 = asyncThunk()(dispatch, getState, extra)
+    await expect(unwrapPromise2.unwrap()).rejects.toEqual(
+      miniSerializeError(error),
+    )
+  })
+  test('rejectWithValue case', async () => {
+    const asyncThunk = createAsyncThunk('test', (_, { rejectWithValue }) => {
+      return rejectWithValue('rejectWithValue!')
+    })
+
+    const unwrapPromise = asyncThunk()(dispatch, getState, extra).then(
+      unwrapResult,
+    )
+
+    await expect(unwrapPromise).rejects.toBe('rejectWithValue!')
+
+    const unwrapPromise2 = asyncThunk()(dispatch, getState, extra)
+    await expect(unwrapPromise2.unwrap()).rejects.toBe('rejectWithValue!')
+  })
+})
+
+describe('idGenerator option', () => {
+  const getState = () => ({})
+  const dispatch = (x: any) => x
+  const extra = {}
+
+  test('idGenerator implementation - can customizes how request IDs are generated', async () => {
+    function makeFakeIdGenerator() {
+      let id = 0
+      return vi.fn(() => {
+        id++
+        return `fake-random-id-${id}`
+      })
+    }
+
+    let generatedRequestId = ''
+
+    const idGenerator = makeFakeIdGenerator()
+    const asyncThunk = createAsyncThunk(
+      'test',
+      async (args: void, { requestId }) => {
+        generatedRequestId = requestId
+      },
+      { idGenerator },
+    )
+
+    // dispatching the thunks should be using the custom id generator
+    const promise0 = asyncThunk()(dispatch, getState, extra)
+    expect(generatedRequestId).toEqual('fake-random-id-1')
+    expect(promise0.requestId).toEqual('fake-random-id-1')
+    expect((await promise0).meta.requestId).toEqual('fake-random-id-1')
+
+    const promise1 = asyncThunk()(dispatch, getState, extra)
+    expect(generatedRequestId).toEqual('fake-random-id-2')
+    expect(promise1.requestId).toEqual('fake-random-id-2')
+    expect((await promise1).meta.requestId).toEqual('fake-random-id-2')
+
+    const promise2 = asyncThunk()(dispatch, getState, extra)
+    expect(generatedRequestId).toEqual('fake-random-id-3')
+    expect(promise2.requestId).toEqual('fake-random-id-3')
+    expect((await promise2).meta.requestId).toEqual('fake-random-id-3')
+
+    generatedRequestId = ''
+    const defaultAsyncThunk = createAsyncThunk(
+      'test',
+      async (args: void, { requestId }) => {
+        generatedRequestId = requestId
+      },
+    )
+    // dispatching the default options thunk should still generate an id,
+    // but not using the custom id generator
+    const promise3 = defaultAsyncThunk()(dispatch, getState, extra)
+    expect(generatedRequestId).toEqual(promise3.requestId)
+    expect(promise3.requestId).not.toEqual('')
+    expect(promise3.requestId).not.toEqual(
+      expect.stringContaining('fake-random-id'),
+    )
+    expect((await promise3).meta.requestId).not.toEqual(
+      expect.stringContaining('fake-fandom-id'),
+    )
+  })
+
+  test('idGenerator should be called with thunkArg', async () => {
+    const customIdGenerator = vi.fn((seed) => `fake-unique-random-id-${seed}`)
+    let generatedRequestId = ''
+    const asyncThunk = createAsyncThunk(
+      'test',
+      async (args: any, { requestId }) => {
+        generatedRequestId = requestId
+      },
+      { idGenerator: customIdGenerator },
+    )
+
+    const thunkArg = 1
+    const expected = 'fake-unique-random-id-1'
+    const asyncThunkPromise = asyncThunk(thunkArg)(dispatch, getState, extra)
+
+    expect(customIdGenerator).toHaveBeenCalledWith(thunkArg)
+    expect(asyncThunkPromise.requestId).toEqual(expected)
+    expect((await asyncThunkPromise).meta.requestId).toEqual(expected)
+  })
+})
+
+test('`condition` will see state changes from a synchronously invoked asyncThunk', () => {
+  type State = ReturnType<typeof store.getState>
+  const onStart = vi.fn()
+  const asyncThunk = createAsyncThunk<
+    void,
+    { force?: boolean },
+    { state: State }
+  >('test', onStart, {
+    condition({ force }, { getState }) {
+      return force || !getState().started
+    },
+  })
+  const store = configureStore({
+    reducer: createReducer({ started: false }, (builder) => {
+      builder.addCase(asyncThunk.pending, (state) => {
+        state.started = true
+      })
+    }),
+  })
+
+  store.dispatch(asyncThunk({ force: false }))
+  expect(onStart).toHaveBeenCalledOnce()
+  store.dispatch(asyncThunk({ force: false }))
+  expect(onStart).toHaveBeenCalledOnce()
+  store.dispatch(asyncThunk({ force: true }))
+  expect(onStart).toHaveBeenCalledTimes(2)
+})
+
+const getNewStore = () =>
+  configureStore({
+    reducer(actions: UnknownAction[] = [], action) {
+      return [...actions, action]
+    },
+  })
+
+describe('meta', () => {
+  let store = getNewStore()
+
+  beforeEach(() => {
+    store = getNewStore()
+  })
+
+  test('pendingMeta', () => {
+    const pendingThunk = createAsyncThunk('test', (arg: string) => {}, {
+      getPendingMeta({ arg, requestId }) {
+        expect(arg).toBe('testArg')
+        expect(requestId).toEqual(expect.any(String))
+        return { extraProp: 'foo' }
+      },
+    })
+    const ret = store.dispatch(pendingThunk('testArg'))
+    expect(store.getState()[1]).toEqual({
+      meta: {
+        arg: 'testArg',
+        extraProp: 'foo',
+        requestId: ret.requestId,
+        requestStatus: 'pending',
+      },
+      payload: undefined,
+      type: 'test/pending',
+    })
+  })
+
+  test('fulfilledMeta', async () => {
+    const fulfilledThunk = createAsyncThunk<
+      string,
+      string,
+      { fulfilledMeta: { extraProp: string } }
+    >('test', (arg: string, { fulfillWithValue }) => {
+      return fulfillWithValue('hooray!', { extraProp: 'bar' })
+    })
+    const ret = store.dispatch(fulfilledThunk('testArg'))
+    expect(await ret).toEqual({
+      meta: {
+        arg: 'testArg',
+        extraProp: 'bar',
+        requestId: ret.requestId,
+        requestStatus: 'fulfilled',
+      },
+      payload: 'hooray!',
+      type: 'test/fulfilled',
+    })
+  })
+
+  test('rejectedMeta', async () => {
+    const fulfilledThunk = createAsyncThunk<
+      string,
+      string,
+      { rejectedMeta: { extraProp: string } }
+    >('test', (arg: string, { rejectWithValue }) => {
+      return rejectWithValue('damn!', { extraProp: 'baz' })
+    })
+    const promise = store.dispatch(fulfilledThunk('testArg'))
+    const ret = await promise
+    expect(ret).toEqual({
+      meta: {
+        arg: 'testArg',
+        extraProp: 'baz',
+        requestId: promise.requestId,
+        requestStatus: 'rejected',
+        rejectedWithValue: true,
+        aborted: false,
+        condition: false,
+      },
+      error: { message: 'Rejected' },
+      payload: 'damn!',
+      type: 'test/rejected',
+    })
+
+    if (ret.meta.requestStatus === 'rejected' && ret.meta.rejectedWithValue) {
+    } else {
+      // could be caused by a `throw`, `abort()` or `condition` - no `rejectedMeta` in that case
+      // @ts-expect-error
+      ret.meta.extraProp
+    }
+  })
+
+  test('typed createAsyncThunk.withTypes', () => {
+    const typedCAT = createAsyncThunk.withTypes<{
+      state: { s: string }
+      rejectValue: string
+      extra: { s: string; n: number }
+    }>()
+    const thunk = typedCAT('a', () => 'b')
+    const expectFunction = expect.any(Function)
+    expect(thunk.fulfilled).toEqual(expectFunction)
+    expect(thunk.pending).toEqual(expectFunction)
+    expect(thunk.rejected).toEqual(expectFunction)
+    expect(thunk.settled).toEqual(expectFunction)
+    expect(thunk.fulfilled.type).toBe('a/fulfilled')
+  })
+  test('createAsyncThunkWrapper using CreateAsyncThunkFunction', async () => {
+    const customSerializeError = () => 'serialized!'
+    const createAppAsyncThunk: CreateAsyncThunkFunction<{
+      serializedErrorType: ReturnType<typeof customSerializeError>
+    }> = (prefix: string, payloadCreator: any, options: any) =>
+      createAsyncThunk(prefix, payloadCreator, {
+        ...options,
+        serializeError: customSerializeError,
+      }) as any
+
+    const asyncThunk = createAppAsyncThunk('test', async () => {
+      throw new Error('Panic!')
+    })
+
+    const promise = store.dispatch(asyncThunk())
+    const result = await promise
+    if (!asyncThunk.rejected.match(result)) {
+      throw new Error('should have thrown')
+    }
+    expect(result.error).toEqual('serialized!')
+  })
+})
+
+describe('dispatch config', () => {
+  let store = getNewStore()
+
+  beforeEach(() => {
+    store = getNewStore()
+  })
+  test('accepts external signal', async () => {
+    const asyncThunk = createAsyncThunk('test', async (_: void, { signal }) => {
+      signal.throwIfAborted()
+      const { promise, reject } = promiseWithResolvers<never>()
+      signal.addEventListener('abort', () => reject(signal.reason))
+      return promise
+    })
+
+    const abortController = new AbortController()
+    const promise = store.dispatch(
+      asyncThunk(undefined, { signal: abortController.signal }),
+    )
+    abortController.abort()
+    await expect(promise.unwrap()).rejects.toThrow(
+      'External signal was aborted',
+    )
+  })
+  test('handles already aborted external signal', async () => {
+    const asyncThunk = createAsyncThunk('test', async (_: void, { signal }) => {
+      signal.throwIfAborted()
+      const { promise, reject } = promiseWithResolvers<never>()
+      signal.addEventListener('abort', () => reject(signal.reason))
+      return promise
+    })
+
+    const signal = AbortSignal.abort()
+    const promise = store.dispatch(asyncThunk(undefined, { signal }))
+    await expect(promise.unwrap()).rejects.toThrow(
+      'Aborted due to condition callback returning false.',
+    )
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/createDraftSafeSelector.test.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/createDraftSafeSelector.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/createDraftSafeSelector.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,43 @@
+import { createDraftSafeSelector, createSelector } from '@reduxjs/toolkit'
+import { produce } from 'immer'
+
+type State = { value: number }
+const selectSelf = (state: State) => state
+
+test('handles normal values correctly', () => {
+  const unsafeSelector = createSelector(selectSelf, (x) => x.value)
+  const draftSafeSelector = createDraftSafeSelector(selectSelf, (x) => x.value)
+
+  let state = { value: 1 }
+  expect(unsafeSelector(state)).toBe(1)
+  expect(draftSafeSelector(state)).toBe(1)
+  expect(draftSafeSelector).toHaveProperty('resultFunc')
+  expect(draftSafeSelector).toHaveProperty('memoizedResultFunc')
+  expect(draftSafeSelector).toHaveProperty('lastResult')
+  expect(draftSafeSelector).toHaveProperty('dependencies')
+  expect(draftSafeSelector).toHaveProperty('recomputations')
+  expect(draftSafeSelector).toHaveProperty('resetRecomputations')
+  expect(draftSafeSelector).toHaveProperty('clearCache')
+
+  state = { value: 2 }
+  expect(unsafeSelector(state)).toBe(2)
+  expect(draftSafeSelector(state)).toBe(2)
+})
+
+test('handles drafts correctly', () => {
+  const unsafeSelector = createSelector(selectSelf, (state) => state.value)
+  const draftSafeSelector = createDraftSafeSelector(
+    selectSelf,
+    (state) => state.value,
+  )
+
+  produce({ value: 1 }, (state) => {
+    expect(unsafeSelector(state)).toBe(1)
+    expect(draftSafeSelector(state)).toBe(1)
+
+    state.value = 2
+
+    expect(unsafeSelector(state)).toBe(1)
+    expect(draftSafeSelector(state)).toBe(2)
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/createDraftSafeSelector.withTypes.test.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/createDraftSafeSelector.withTypes.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/createDraftSafeSelector.withTypes.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,49 @@
+import { createDraftSafeSelector } from '@reduxjs/toolkit'
+
+interface Todo {
+  id: number
+  completed: boolean
+}
+
+interface Alert {
+  id: number
+  read: boolean
+}
+
+interface RootState {
+  todos: Todo[]
+  alerts: Alert[]
+}
+
+const rootState: RootState = {
+  todos: [
+    { id: 0, completed: false },
+    { id: 1, completed: false },
+  ],
+  alerts: [
+    { id: 0, read: false },
+    { id: 1, read: false },
+  ],
+}
+
+describe(createDraftSafeSelector.withTypes, () => {
+  const createTypedDraftSafeSelector =
+    createDraftSafeSelector.withTypes<RootState>()
+
+  test('should return createDraftSafeSelector', () => {
+    expect(createTypedDraftSafeSelector.withTypes).toEqual(expect.any(Function))
+
+    expect(createTypedDraftSafeSelector.withTypes().withTypes).toEqual(
+      expect.any(Function),
+    )
+
+    expect(createTypedDraftSafeSelector).toBe(createDraftSafeSelector)
+
+    const selectTodoIds = createTypedDraftSafeSelector(
+      [(state) => state.todos],
+      (todos) => todos.map(({ id }) => id),
+    )
+
+    expect(selectTodoIds(rootState)).to.be.an('array').that.is.not.empty
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/createEntityAdapter.test-d.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/createEntityAdapter.test-d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/createEntityAdapter.test-d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,161 @@
+import type {
+  ActionCreatorWithPayload,
+  ActionCreatorWithoutPayload,
+  EntityAdapter,
+  EntityId,
+  EntityStateAdapter,
+  Update,
+} from '@reduxjs/toolkit'
+import { createEntityAdapter, createSlice } from '@reduxjs/toolkit'
+
+function extractReducers<T, Id extends EntityId>(
+  adapter: EntityAdapter<T, Id>,
+): EntityStateAdapter<T, Id> {
+  const { selectId, sortComparer, getInitialState, getSelectors, ...rest } =
+    adapter
+  return rest
+}
+
+describe('type tests', () => {
+  test('should be usable in a slice, with all the "reducer-like" functions', () => {
+    type Id = string & { readonly __tag: unique symbol }
+    type Entity = {
+      id: Id
+    }
+    const adapter = createEntityAdapter<Entity>()
+    const slice = createSlice({
+      name: 'test',
+      initialState: adapter.getInitialState(),
+      reducers: {
+        ...extractReducers(adapter),
+      },
+    })
+
+    expectTypeOf(slice.actions.addOne).toMatchTypeOf<
+      ActionCreatorWithPayload<Entity>
+    >()
+
+    expectTypeOf(slice.actions.addMany).toMatchTypeOf<
+      ActionCreatorWithPayload<ReadonlyArray<Entity> | Record<string, Entity>>
+    >()
+
+    expectTypeOf(slice.actions.setAll).toMatchTypeOf<
+      ActionCreatorWithPayload<ReadonlyArray<Entity> | Record<string, Entity>>
+    >()
+
+    expectTypeOf(slice.actions.removeOne).toMatchTypeOf<
+      ActionCreatorWithPayload<Id>
+    >()
+
+    expectTypeOf(slice.actions.addMany).not.toMatchTypeOf<
+      ActionCreatorWithPayload<Entity[] | Record<string, Entity>>
+    >()
+
+    expectTypeOf(slice.actions.setAll).not.toMatchTypeOf<
+      ActionCreatorWithPayload<ReadonlyArray<Id>>
+    >()
+
+    expectTypeOf(slice.actions.removeOne).toMatchTypeOf<
+      ActionCreatorWithPayload<Id>
+    >()
+
+    expectTypeOf(slice.actions.removeMany).toMatchTypeOf<
+      ActionCreatorWithPayload<ReadonlyArray<Id>>
+    >()
+
+    expectTypeOf(slice.actions.removeMany).not.toMatchTypeOf<
+      ActionCreatorWithPayload<EntityId[]>
+    >()
+
+    expectTypeOf(
+      slice.actions.removeAll,
+    ).toMatchTypeOf<ActionCreatorWithoutPayload>()
+
+    expectTypeOf(slice.actions.updateOne).toMatchTypeOf<
+      ActionCreatorWithPayload<Update<Entity, Id>>
+    >()
+
+    expectTypeOf(slice.actions.updateMany).not.toMatchTypeOf<
+      ActionCreatorWithPayload<Update<Entity, Id>[]>
+    >()
+
+    expectTypeOf(slice.actions.upsertOne).toMatchTypeOf<
+      ActionCreatorWithPayload<Entity>
+    >()
+
+    expectTypeOf(slice.actions.updateMany).toMatchTypeOf<
+      ActionCreatorWithPayload<ReadonlyArray<Update<Entity, Id>>>
+    >()
+
+    expectTypeOf(slice.actions.upsertOne).toMatchTypeOf<
+      ActionCreatorWithPayload<Entity>
+    >()
+
+    expectTypeOf(slice.actions.upsertMany).toMatchTypeOf<
+      ActionCreatorWithPayload<ReadonlyArray<Entity> | Record<string, Entity>>
+    >()
+
+    expectTypeOf(slice.actions.upsertMany).not.toMatchTypeOf<
+      ActionCreatorWithPayload<Entity[] | Record<string, Entity>>
+    >()
+  })
+
+  test('should not be able to mix with a different EntityAdapter', () => {
+    type Entity = {
+      id: EntityId
+      value: string
+    }
+    type Entity2 = {
+      id: EntityId
+      value2: string
+    }
+    const adapter = createEntityAdapter<Entity>()
+    const adapter2 = createEntityAdapter<Entity2>()
+    createSlice({
+      name: 'test',
+      initialState: adapter.getInitialState(),
+      reducers: {
+        addOne: adapter.addOne,
+        // @ts-expect-error
+        addOne2: adapter2.addOne,
+      },
+    })
+  })
+
+  test('should be usable in a slice with extra properties', () => {
+    type Entity = { id: EntityId; value: string }
+    const adapter = createEntityAdapter<Entity>()
+    createSlice({
+      name: 'test',
+      initialState: adapter.getInitialState({ extraData: 'test' }),
+      reducers: {
+        addOne: adapter.addOne,
+      },
+    })
+  })
+
+  test('should not be usable in a slice with an unfitting state', () => {
+    type Entity = { id: EntityId; value: string }
+    const adapter = createEntityAdapter<Entity>()
+    createSlice({
+      name: 'test',
+      initialState: { somethingElse: '' },
+      reducers: {
+        // @ts-expect-error
+        addOne: adapter.addOne,
+      },
+    })
+  })
+
+  test('should not be able to create an adapter unless the type has an Id or an idSelector is provided', () => {
+    type Entity = {
+      value: string
+    }
+    // @ts-expect-error
+    const adapter = createEntityAdapter<Entity>()
+    const adapter2: EntityAdapter<Entity, Entity['value']> =
+      createEntityAdapter({
+        selectId: (e: Entity) => e.value,
+      })
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/createReducer.test-d.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/createReducer.test-d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/createReducer.test-d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,77 @@
+import type { ActionReducerMapBuilder, Reducer } from '@reduxjs/toolkit'
+import { createAction, createReducer } from '@reduxjs/toolkit'
+
+describe('type tests', () => {
+  test('createReducer() infers type of returned reducer.', () => {
+    const incrementHandler = (
+      state: number,
+      action: { type: 'increment'; payload: number },
+    ) => state + 1
+
+    const decrementHandler = (
+      state: number,
+      action: { type: 'decrement'; payload: number },
+    ) => state - 1
+
+    const reducer = createReducer(0 as number, (builder) => {
+      builder
+        .addCase('increment', incrementHandler)
+        .addCase('decrement', decrementHandler)
+    })
+
+    expectTypeOf(reducer).toMatchTypeOf<Reducer<number>>()
+
+    expectTypeOf(reducer).not.toMatchTypeOf<Reducer<string>>()
+  })
+
+  test('createReducer() state type can be specified explicitly.', () => {
+    const incrementHandler = (
+      state: number,
+      action: { type: 'increment'; payload: number },
+    ) => state + action.payload
+
+    const decrementHandler = (
+      state: number,
+      action: { type: 'decrement'; payload: number },
+    ) => state - action.payload
+
+    createReducer(0 as number, (builder) => {
+      builder
+        .addCase('increment', incrementHandler)
+        .addCase('decrement', decrementHandler)
+    })
+
+    // @ts-expect-error
+    createReducer<string>(0 as number, (builder) => {
+      expectTypeOf(builder.addCase)
+        .parameter(1)
+        .not.toMatchTypeOf(incrementHandler)
+
+      expectTypeOf(builder.addCase)
+        .parameter(1)
+        .not.toMatchTypeOf(decrementHandler)
+    })
+  })
+
+  test('createReducer() ensures state type is mutable within a case reducer.', () => {
+    const initialState: { readonly counter: number } = { counter: 0 }
+
+    createReducer(initialState, (builder) => {
+      builder.addCase('increment', (state) => {
+        state.counter += 1
+      })
+    })
+  })
+
+  test('builder callback for actionMap', () => {
+    const increment = createAction<number, 'increment'>('increment')
+
+    const reducer = createReducer(0, (builder) =>
+      expectTypeOf(builder).toEqualTypeOf<ActionReducerMapBuilder<number>>(),
+    )
+
+    expectTypeOf(reducer(0, increment(5))).toBeNumber()
+
+    expectTypeOf(reducer(0, increment(5))).not.toBeString()
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/createReducer.test.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/createReducer.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/createReducer.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,693 @@
+import type {
+  CaseReducer,
+  Draft,
+  PayloadAction,
+  Reducer,
+  UnknownAction,
+} from '@reduxjs/toolkit'
+import {
+  createAction,
+  createAsyncThunk,
+  createNextState,
+  createReducer,
+  isPlainObject,
+} from '@reduxjs/toolkit'
+import { waitMs } from './utils/helpers'
+
+interface Todo {
+  text: string
+  completed?: boolean
+}
+
+interface AddTodoPayload {
+  newTodo: Todo
+}
+
+interface ToggleTodoPayload {
+  index: number
+}
+
+type TodoState = Todo[]
+type TodosReducer = Reducer<TodoState, PayloadAction<any>>
+type AddTodoReducer = CaseReducer<
+  TodoState,
+  PayloadAction<AddTodoPayload, 'ADD_TODO'>
+>
+
+type ToggleTodoReducer = CaseReducer<
+  TodoState,
+  PayloadAction<ToggleTodoPayload, 'TOGGLE_TODO'>
+>
+
+type CreateReducer = typeof createReducer
+
+const addTodoThunk = createAsyncThunk('todos/add', (todo: Todo) => todo)
+
+describe('createReducer', () => {
+  describe('given impure reducers with immer', () => {
+    const addTodo: AddTodoReducer = (state, action) => {
+      const { newTodo } = action.payload
+
+      // Can safely call state.push() here
+      state.push({ ...newTodo, completed: false })
+    }
+
+    const toggleTodo: ToggleTodoReducer = (state, action) => {
+      const { index } = action.payload
+
+      const todo = state[index]
+      // Can directly modify the todo object
+      todo.completed = !todo.completed
+    }
+
+    const todosReducer = createReducer([] as TodoState, (builder) => {
+      builder.addCase('ADD_TODO', addTodo).addCase('TOGGLE_TODO', toggleTodo)
+    })
+
+    behavesLikeReducer(todosReducer)
+  })
+
+  describe('Deprecation warnings', () => {
+    beforeEach(() => {
+      vi.resetModules()
+    })
+
+    afterEach(() => {
+      vi.unstubAllEnvs()
+    })
+
+    it('Throws an error if the legacy object notation is used', async () => {
+      const { createReducer } = await import('../createReducer')
+      const wrapper = () => {
+        const dummyReducer = (createReducer as CreateReducer)(
+          [] as TodoState,
+          // @ts-ignore
+          {},
+        )
+      }
+
+      expect(wrapper).toThrowError(
+        /The object notation for `createReducer` has been removed/,
+      )
+
+      expect(wrapper).toThrowError(
+        /The object notation for `createReducer` has been removed/,
+      )
+    })
+
+    it('Crashes in production', async () => {
+      vi.stubEnv('NODE_ENV', 'production')
+      const { createReducer } = await import('../createReducer')
+      const wrapper = () => {
+        const dummyReducer = (createReducer as CreateReducer)(
+          [] as TodoState,
+          // @ts-ignore
+          {},
+        )
+      }
+
+      expect(wrapper).toThrowError()
+    })
+  })
+
+  describe('Immer in a production environment', () => {
+    beforeEach(() => {
+      vi.resetModules()
+      vi.stubEnv('NODE_ENV', 'production')
+    })
+
+    afterEach(() => {
+      vi.unstubAllEnvs()
+    })
+
+    test('Freezes data in production', async () => {
+      const { createReducer } = await import('../createReducer')
+      const addTodo: AddTodoReducer = (state, action) => {
+        const { newTodo } = action.payload
+        state.push({ ...newTodo, completed: false })
+      }
+
+      const toggleTodo: ToggleTodoReducer = (state, action) => {
+        const { index } = action.payload
+        const todo = state[index]
+        todo.completed = !todo.completed
+      }
+
+      const todosReducer = createReducer([] as TodoState, (builder) => {
+        builder.addCase('ADD_TODO', addTodo).addCase('TOGGLE_TODO', toggleTodo)
+      })
+
+      const result = todosReducer([], {
+        type: 'ADD_TODO',
+        payload: { text: 'Buy milk' },
+      })
+
+      const mutateStateOutsideReducer = () => (result[0].text = 'edited')
+      expect(mutateStateOutsideReducer).toThrowError(
+        'Cannot add property text, object is not extensible',
+      )
+    })
+
+    test('Freezes initial state', () => {
+      const initialState = [{ text: 'Buy milk' }]
+      const todosReducer = createReducer(initialState, () => {})
+      const frozenInitialState = todosReducer(undefined, { type: 'dummy' })
+
+      const mutateStateOutsideReducer = () =>
+        (frozenInitialState[0].text = 'edited')
+      expect(mutateStateOutsideReducer).toThrowError(
+        /Cannot assign to read only property/,
+      )
+    })
+    test('does not throw error if initial state is not draftable', () => {
+      expect(() =>
+        createReducer(new URLSearchParams(), () => {}),
+      ).not.toThrowError()
+    })
+  })
+
+  describe('given pure reducers with immutable updates', () => {
+    const addTodo: AddTodoReducer = (state, action) => {
+      const { newTodo } = action.payload
+
+      // Updates the state immutably without relying on immer
+      return state.concat({ ...newTodo, completed: false })
+    }
+
+    const toggleTodo: ToggleTodoReducer = (state, action) => {
+      const { index } = action.payload
+
+      // Updates the todo object immutably withot relying on immer
+      return state.map((todo, i) => {
+        if (i !== index) return todo
+        return { ...todo, completed: !todo.completed }
+      })
+    }
+
+    const todosReducer = createReducer([] as TodoState, (builder) => {
+      builder.addCase('ADD_TODO', addTodo).addCase('TOGGLE_TODO', toggleTodo)
+    })
+
+    behavesLikeReducer(todosReducer)
+  })
+
+  describe('Accepts a lazy state init function to generate initial state', () => {
+    const addTodo: AddTodoReducer = (state, action) => {
+      const { newTodo } = action.payload
+      state.push({ ...newTodo, completed: false })
+    }
+
+    const toggleTodo: ToggleTodoReducer = (state, action) => {
+      const { index } = action.payload
+      const todo = state[index]
+      todo.completed = !todo.completed
+    }
+
+    const lazyStateInit = () => [] as TodoState
+
+    const todosReducer = createReducer([] as TodoState, (builder) => {
+      builder.addCase('ADD_TODO', addTodo).addCase('TOGGLE_TODO', toggleTodo)
+    })
+
+    behavesLikeReducer(todosReducer)
+
+    it('Should only call the init function when `undefined` state is passed in', () => {
+      const spy = vi.fn().mockReturnValue(42)
+
+      const dummyReducer = createReducer(spy, () => {})
+      expect(spy).not.toHaveBeenCalled()
+
+      dummyReducer(123, { type: 'dummy' })
+      expect(spy).not.toHaveBeenCalled()
+
+      const initialState = dummyReducer(undefined, { type: 'dummy' })
+      expect(spy).toHaveBeenCalledOnce()
+    })
+  })
+
+  describe('given draft state from immer', () => {
+    const addTodo: AddTodoReducer = (state, action) => {
+      const { newTodo } = action.payload
+
+      // Can safely call state.push() here
+      state.push({ ...newTodo, completed: false })
+    }
+
+    const toggleTodo: ToggleTodoReducer = (state, action) => {
+      const { index } = action.payload
+
+      const todo = state[index]
+      // Can directly modify the todo object
+      todo.completed = !todo.completed
+    }
+
+    const todosReducer = createReducer([] as TodoState, (builder) => {
+      builder.addCase('ADD_TODO', addTodo).addCase('TOGGLE_TODO', toggleTodo)
+    })
+
+    const wrappedReducer: TodosReducer = (state = [], action) => {
+      return createNextState(state, (draft: Draft<TodoState>) => {
+        todosReducer(draft, action)
+      })
+    }
+
+    behavesLikeReducer(wrappedReducer)
+  })
+
+  describe('builder callback for actionMap', () => {
+    const increment = createAction<number, 'increment'>('increment')
+    const decrement = createAction<number, 'decrement'>('decrement')
+
+    test('can be used with ActionCreators', () => {
+      const reducer = createReducer(0, (builder) =>
+        builder
+          .addCase(increment, (state, action) => state + action.payload)
+          .addCase(decrement, (state, action) => state - action.payload),
+      )
+      expect(reducer(0, increment(5))).toBe(5)
+      expect(reducer(5, decrement(5))).toBe(0)
+    })
+    test('can be used with string types', () => {
+      const reducer = createReducer(0, (builder) =>
+        builder
+          .addCase(
+            'increment',
+            (state, action: { type: 'increment'; payload: number }) =>
+              state + action.payload,
+          )
+          .addCase(
+            'decrement',
+            (state, action: { type: 'decrement'; payload: number }) =>
+              state - action.payload,
+          ),
+      )
+      expect(reducer(0, increment(5))).toBe(5)
+      expect(reducer(5, decrement(5))).toBe(0)
+    })
+    test('can be used with ActionCreators and string types combined', () => {
+      const reducer = createReducer(0, (builder) =>
+        builder
+          .addCase(increment, (state, action) => state + action.payload)
+          .addCase(
+            'decrement',
+            (state, action: { type: 'decrement'; payload: number }) =>
+              state - action.payload,
+          ),
+      )
+      expect(reducer(0, increment(5))).toBe(5)
+      expect(reducer(5, decrement(5))).toBe(0)
+    })
+    test('will throw an error when returning undefined from a non-draftable state', () => {
+      const reducer = createReducer(0, (builder) =>
+        builder.addCase(
+          'decrement',
+          (state, action: { type: 'decrement'; payload: number }) => {},
+        ),
+      )
+      expect(() => reducer(5, decrement(5))).toThrowErrorMatchingInlineSnapshot(
+        `[Error: A case reducer on a non-draftable value must not return undefined]`,
+      )
+    })
+    test('allows you to return undefined if the state was null, thus skipping an update', () => {
+      const reducer = createReducer(null as number | null, (builder) =>
+        builder.addCase(
+          'decrement',
+          (state, action: { type: 'decrement'; payload: number }) => {
+            if (typeof state === 'number') {
+              return state - action.payload
+            }
+            return undefined
+          },
+        ),
+      )
+      expect(reducer(0, decrement(5))).toBe(-5)
+      expect(reducer(null, decrement(5))).toBe(null)
+    })
+    test('allows you to return null', () => {
+      const reducer = createReducer(0 as number | null, (builder) =>
+        builder.addCase(
+          'decrement',
+          (state, action: { type: 'decrement'; payload: number }) => {
+            return null
+          },
+        ),
+      )
+      expect(reducer(5, decrement(5))).toBe(null)
+    })
+    test('allows you to return 0', () => {
+      const reducer = createReducer(0, (builder) =>
+        builder.addCase(
+          'decrement',
+          (state, action: { type: 'decrement'; payload: number }) =>
+            state - action.payload,
+        ),
+      )
+      expect(reducer(5, decrement(5))).toBe(0)
+    })
+    test('will throw if the same type is used twice', () => {
+      expect(() => {
+        createReducer(0, (builder) => {
+          builder
+            .addCase(increment, (state, action) => state + action.payload)
+            .addCase(increment, (state, action) => state + action.payload)
+            .addCase(decrement, (state, action) => state - action.payload)
+        })
+      }).toThrowErrorMatchingInlineSnapshot(
+        `[Error: \`builder.addCase\` cannot be called with two reducers for the same action type 'increment']`,
+      )
+      expect(() => {
+        createReducer(0, (builder) => {
+          builder
+            .addCase(increment, (state, action) => state + action.payload)
+            .addCase('increment', (state) => state + 1)
+            .addCase(decrement, (state, action) => state - action.payload)
+        })
+      }).toThrowErrorMatchingInlineSnapshot(
+        `[Error: \`builder.addCase\` cannot be called with two reducers for the same action type 'increment']`,
+      )
+    })
+
+    test('will throw if an empty type is used', () => {
+      const customActionCreator = (payload: number) => ({
+        type: 'custom_action',
+        payload,
+      })
+      customActionCreator.type = ''
+      expect(() => {
+        createReducer(0, (builder) => {
+          builder.addCase(
+            customActionCreator,
+            (state, action) => state + action.payload,
+          )
+        })
+      }).toThrowErrorMatchingInlineSnapshot(
+        `[Error: \`builder.addCase\` cannot be called with an empty action type]`,
+      )
+    })
+  })
+
+  describe('builder "addMatcher" method', () => {
+    const prepareNumberAction = (payload: number) => ({
+      payload,
+      meta: { type: 'number_action' },
+    })
+    const prepareStringAction = (payload: string) => ({
+      payload,
+      meta: { type: 'string_action' },
+    })
+
+    const numberActionMatcher = (
+      a: UnknownAction,
+    ): a is PayloadAction<number> =>
+      isPlainObject(a.meta) &&
+      'type' in a.meta &&
+      (a.meta as Record<'type', unknown>).type === 'number_action'
+
+    const stringActionMatcher = (
+      a: UnknownAction,
+    ): a is PayloadAction<string> =>
+      isPlainObject(a.meta) &&
+      'type' in a.meta &&
+      (a.meta as Record<'type', unknown>).type === 'string_action'
+
+    const incrementBy = createAction('increment', prepareNumberAction)
+    const decrementBy = createAction('decrement', prepareNumberAction)
+    const concatWith = createAction('concat', prepareStringAction)
+
+    const initialState = { numberActions: 0, stringActions: 0 }
+
+    test('uses the reducer of matching actionMatchers', () => {
+      const reducer = createReducer(initialState, (builder) =>
+        builder
+          .addMatcher(numberActionMatcher, (state) => {
+            state.numberActions += 1
+          })
+          .addMatcher(stringActionMatcher, (state) => {
+            state.stringActions += 1
+          }),
+      )
+      expect(reducer(undefined, incrementBy(1))).toEqual({
+        numberActions: 1,
+        stringActions: 0,
+      })
+      expect(reducer(undefined, decrementBy(1))).toEqual({
+        numberActions: 1,
+        stringActions: 0,
+      })
+      expect(reducer(undefined, concatWith('foo'))).toEqual({
+        numberActions: 0,
+        stringActions: 1,
+      })
+    })
+    test('falls back to defaultCase', () => {
+      const reducer = createReducer(initialState, (builder) =>
+        builder
+          .addCase(concatWith, (state) => {
+            state.stringActions += 1
+          })
+          .addMatcher(numberActionMatcher, (state) => {
+            state.numberActions += 1
+          })
+          .addDefaultCase((state) => {
+            state.numberActions = -1
+            state.stringActions = -1
+          }),
+      )
+      expect(reducer(undefined, { type: 'somethingElse' })).toEqual({
+        numberActions: -1,
+        stringActions: -1,
+      })
+    })
+    test('runs reducer cases followed by all matching actionMatchers', () => {
+      const reducer = createReducer(initialState, (builder) =>
+        builder
+          .addCase(incrementBy, (state) => {
+            state.numberActions = state.numberActions * 10 + 1
+          })
+          .addMatcher(numberActionMatcher, (state) => {
+            state.numberActions = state.numberActions * 10 + 2
+          })
+          .addMatcher(stringActionMatcher, (state) => {
+            state.stringActions = state.stringActions * 10 + 1
+          })
+          .addMatcher(numberActionMatcher, (state) => {
+            state.numberActions = state.numberActions * 10 + 3
+          }),
+      )
+      expect(reducer(undefined, incrementBy(1))).toEqual({
+        numberActions: 123,
+        stringActions: 0,
+      })
+      expect(reducer(undefined, decrementBy(1))).toEqual({
+        numberActions: 23,
+        stringActions: 0,
+      })
+      expect(reducer(undefined, concatWith('foo'))).toEqual({
+        numberActions: 0,
+        stringActions: 1,
+      })
+    })
+    test('works with `actionCreator.match`', () => {
+      const reducer = createReducer(initialState, (builder) =>
+        builder.addMatcher(incrementBy.match, (state) => {
+          state.numberActions += 100
+        }),
+      )
+      expect(reducer(undefined, incrementBy(1))).toEqual({
+        numberActions: 100,
+        stringActions: 0,
+      })
+    })
+    test('calling addCase, addMatcher and addDefaultCase in a nonsensical order should result in an error in development mode', () => {
+      expect(() =>
+        createReducer(initialState, (builder: any) =>
+          builder
+            .addMatcher(numberActionMatcher, () => {})
+            .addCase(incrementBy, () => {}),
+        ),
+      ).toThrowErrorMatchingInlineSnapshot(
+        `[Error: \`builder.addCase\` should only be called before calling \`builder.addMatcher\`]`,
+      )
+      expect(() =>
+        createReducer(initialState, (builder: any) =>
+          builder.addDefaultCase(() => {}).addCase(incrementBy, () => {}),
+        ),
+      ).toThrowErrorMatchingInlineSnapshot(
+        `[Error: \`builder.addCase\` should only be called before calling \`builder.addDefaultCase\`]`,
+      )
+      expect(() =>
+        createReducer(initialState, (builder: any) =>
+          builder
+            .addDefaultCase(() => {})
+            .addMatcher(numberActionMatcher, () => {}),
+        ),
+      ).toThrowErrorMatchingInlineSnapshot(
+        `[Error: \`builder.addMatcher\` should only be called before calling \`builder.addDefaultCase\`]`,
+      )
+      expect(() =>
+        createReducer(initialState, (builder: any) =>
+          builder.addDefaultCase(() => {}).addDefaultCase(() => {}),
+        ),
+      ).toThrowErrorMatchingInlineSnapshot(
+        `[Error: \`builder.addDefaultCase\` can only be called once]`,
+      )
+    })
+  })
+  describe('builder "addAsyncThunk" method', () => {
+    const initialState = { todos: [] as Todo[], loading: false, errored: false }
+    test('uses the matching reducer for each action type', () => {
+      const reducer = createReducer(initialState, (builder) =>
+        builder.addAsyncThunk(addTodoThunk, {
+          pending(state) {
+            state.loading = true
+          },
+          fulfilled(state, action) {
+            state.todos.push(action.payload)
+          },
+          rejected(state) {
+            state.errored = true
+          },
+          settled(state) {
+            state.loading = false
+          },
+        }),
+      )
+      const todo: Todo = { text: 'test' }
+      expect(reducer(undefined, addTodoThunk.pending('test', todo))).toEqual({
+        todos: [],
+        loading: true,
+        errored: false,
+      })
+      expect(
+        reducer(undefined, addTodoThunk.fulfilled(todo, 'test', todo)),
+      ).toEqual({
+        todos: [todo],
+        loading: false,
+        errored: false,
+      })
+      expect(
+        reducer(undefined, addTodoThunk.rejected(new Error(), 'test', todo)),
+      ).toEqual({
+        todos: [],
+        loading: false,
+        errored: true,
+      })
+    })
+    test('calling addAsyncThunk after addDefaultCase should result in an error in development mode', () => {
+      expect(() =>
+        createReducer(initialState, (builder: any) =>
+          builder.addDefaultCase(() => {}).addAsyncThunk(addTodoThunk, {}),
+        ),
+      ).toThrowErrorMatchingInlineSnapshot(
+        `[Error: \`builder.addAsyncThunk\` should only be called before calling \`builder.addDefaultCase\`]`,
+      )
+    })
+  })
+})
+
+function behavesLikeReducer(todosReducer: TodosReducer) {
+  it('should handle initial state', () => {
+    const initialAction = { type: '', payload: undefined }
+    expect(todosReducer(undefined, initialAction)).toEqual([])
+  })
+
+  it('should handle ADD_TODO', () => {
+    expect(
+      todosReducer([], {
+        type: 'ADD_TODO',
+        payload: { newTodo: { text: 'Run the tests' } },
+      }),
+    ).toEqual([
+      {
+        text: 'Run the tests',
+        completed: false,
+      },
+    ])
+
+    expect(
+      todosReducer(
+        [
+          {
+            text: 'Run the tests',
+            completed: false,
+          },
+        ],
+        {
+          type: 'ADD_TODO',
+          payload: { newTodo: { text: 'Use Redux' } },
+        },
+      ),
+    ).toEqual([
+      {
+        text: 'Run the tests',
+        completed: false,
+      },
+      {
+        text: 'Use Redux',
+        completed: false,
+      },
+    ])
+
+    expect(
+      todosReducer(
+        [
+          {
+            text: 'Run the tests',
+            completed: false,
+          },
+          {
+            text: 'Use Redux',
+            completed: false,
+          },
+        ],
+        {
+          type: 'ADD_TODO',
+          payload: { newTodo: { text: 'Fix the tests' } },
+        },
+      ),
+    ).toEqual([
+      {
+        text: 'Run the tests',
+        completed: false,
+      },
+      {
+        text: 'Use Redux',
+        completed: false,
+      },
+      {
+        text: 'Fix the tests',
+        completed: false,
+      },
+    ])
+  })
+
+  it('should handle TOGGLE_TODO', () => {
+    expect(
+      todosReducer(
+        [
+          {
+            text: 'Run the tests',
+            completed: false,
+          },
+          {
+            text: 'Use Redux',
+            completed: false,
+          },
+        ],
+        {
+          type: 'TOGGLE_TODO',
+          payload: { index: 0 },
+        },
+      ),
+    ).toEqual([
+      {
+        text: 'Run the tests',
+        completed: true,
+      },
+      {
+        text: 'Use Redux',
+        completed: false,
+      },
+    ])
+  })
+}
Index: node_modules/@reduxjs/toolkit/src/tests/createSlice.test-d.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/createSlice.test-d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/createSlice.test-d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,995 @@
+import type {
+  Action,
+  ActionCreatorWithNonInferrablePayload,
+  ActionCreatorWithOptionalPayload,
+  ActionCreatorWithPayload,
+  ActionCreatorWithPreparedPayload,
+  ActionCreatorWithoutPayload,
+  ActionReducerMapBuilder,
+  AsyncThunk,
+  CaseReducer,
+  PayloadAction,
+  PayloadActionCreator,
+  Reducer,
+  ReducerCreators,
+  SerializedError,
+  SliceCaseReducers,
+  ThunkDispatch,
+  UnknownAction,
+  ValidateSliceCaseReducers,
+} from '@reduxjs/toolkit'
+import {
+  asyncThunkCreator,
+  buildCreateSlice,
+  configureStore,
+  createAction,
+  createAsyncThunk,
+  createSlice,
+  isRejected,
+} from '@reduxjs/toolkit'
+import { castDraft } from 'immer'
+
+describe('type tests', () => {
+  const counterSlice = createSlice({
+    name: 'counter',
+    initialState: 0,
+    reducers: {
+      increment: (state: number, action) => state + action.payload,
+      decrement: (state: number, action) => state - action.payload,
+    },
+  })
+
+  test('Slice name is strongly typed.', () => {
+    const uiSlice = createSlice({
+      name: 'ui',
+      initialState: 0,
+      reducers: {
+        goToNext: (state: number, action) => state + action.payload,
+        goToPrevious: (state: number, action) => state - action.payload,
+      },
+    })
+
+    const actionCreators = {
+      [counterSlice.name]: { ...counterSlice.actions },
+      [uiSlice.name]: { ...uiSlice.actions },
+    }
+
+    expectTypeOf(counterSlice.actions).toEqualTypeOf(actionCreators.counter)
+
+    expectTypeOf(uiSlice.actions).toEqualTypeOf(actionCreators.ui)
+
+    expectTypeOf(actionCreators).not.toHaveProperty('anyKey')
+  })
+
+  test("createSlice() infers the returned slice's type.", () => {
+    const firstAction = createAction<{ count: number }>('FIRST_ACTION')
+
+    const slice = createSlice({
+      name: 'counter',
+      initialState: 0,
+      reducers: {
+        increment: (state: number, action) => state + action.payload,
+        decrement: (state: number, action) => state - action.payload,
+      },
+      extraReducers: (builder) => {
+        builder.addCase(
+          firstAction,
+          (state, action) => state + action.payload.count,
+        )
+      },
+    })
+
+    test('Reducer', () => {
+      expectTypeOf(slice.reducer).toMatchTypeOf<
+        Reducer<number, PayloadAction>
+      >()
+
+      expectTypeOf(slice.reducer).not.toMatchTypeOf<
+        Reducer<string, PayloadAction>
+      >()
+    })
+
+    test('Actions', () => {
+      slice.actions.increment(1)
+      slice.actions.decrement(1)
+
+      expectTypeOf(slice.actions).not.toHaveProperty('other')
+    })
+  })
+
+  test('Slice action creator types are inferred.', () => {
+    const counter = createSlice({
+      name: 'counter',
+      initialState: 0,
+      reducers: {
+        increment: (state) => state + 1,
+        decrement: (
+          state,
+          { payload = 1 }: PayloadAction<number | undefined>,
+        ) => state - payload,
+        multiply: (state, { payload }: PayloadAction<number | number[]>) =>
+          Array.isArray(payload)
+            ? payload.reduce((acc, val) => acc * val, state)
+            : state * payload,
+        addTwo: {
+          reducer: (s, { payload }: PayloadAction<number>) => s + payload,
+          prepare: (a: number, b: number) => ({
+            payload: a + b,
+          }),
+        },
+      },
+    })
+
+    expectTypeOf(
+      counter.actions.increment,
+    ).toMatchTypeOf<ActionCreatorWithoutPayload>()
+
+    counter.actions.increment()
+
+    expectTypeOf(counter.actions.decrement).toMatchTypeOf<
+      ActionCreatorWithOptionalPayload<number | undefined>
+    >()
+
+    counter.actions.decrement()
+    counter.actions.decrement(2)
+
+    expectTypeOf(counter.actions.multiply).toMatchTypeOf<
+      ActionCreatorWithPayload<number | number[]>
+    >()
+
+    counter.actions.multiply(2)
+    counter.actions.multiply([2, 3, 4])
+
+    expectTypeOf(counter.actions.addTwo).toMatchTypeOf<
+      ActionCreatorWithPreparedPayload<[number, number], number>
+    >()
+
+    counter.actions.addTwo(1, 2)
+
+    expectTypeOf(counter.actions.multiply).parameters.not.toMatchTypeOf<[]>()
+
+    expectTypeOf(counter.actions.multiply).parameter(0).not.toBeString()
+
+    expectTypeOf(counter.actions.addTwo).parameters.not.toMatchTypeOf<
+      [number]
+    >()
+
+    expectTypeOf(counter.actions.addTwo).parameters.toEqualTypeOf<
+      [number, number]
+    >()
+  })
+
+  test('Slice action creator types properties are strongly typed', () => {
+    const counter = createSlice({
+      name: 'counter',
+      initialState: 0,
+      reducers: {
+        increment: (state) => state + 1,
+        decrement: (state) => state - 1,
+        multiply: (state, { payload }: PayloadAction<number | number[]>) =>
+          Array.isArray(payload)
+            ? payload.reduce((acc, val) => acc * val, state)
+            : state * payload,
+      },
+    })
+
+    expectTypeOf(
+      counter.actions.increment.type,
+    ).toEqualTypeOf<'counter/increment'>()
+
+    expectTypeOf(
+      counter.actions.increment().type,
+    ).toEqualTypeOf<'counter/increment'>()
+
+    expectTypeOf(
+      counter.actions.decrement.type,
+    ).toEqualTypeOf<'counter/decrement'>()
+
+    expectTypeOf(
+      counter.actions.decrement().type,
+    ).toEqualTypeOf<'counter/decrement'>()
+
+    expectTypeOf(
+      counter.actions.multiply.type,
+    ).toEqualTypeOf<'counter/multiply'>()
+
+    expectTypeOf(
+      counter.actions.multiply(1).type,
+    ).toEqualTypeOf<'counter/multiply'>()
+
+    expectTypeOf(
+      counter.actions.increment.type,
+    ).not.toMatchTypeOf<'increment'>()
+  })
+
+  test('Slice action creator types are inferred for enhanced reducers.', () => {
+    const counter = createSlice({
+      name: 'test',
+      initialState: { counter: 0, concat: '' },
+      reducers: {
+        incrementByStrLen: {
+          reducer: (state, action: PayloadAction<number>) => {
+            state.counter += action.payload
+          },
+          prepare: (payload: string) => ({
+            payload: payload.length,
+          }),
+        },
+        concatMetaStrLen: {
+          reducer: (state, action: PayloadAction<string>) => {
+            state.concat += action.payload
+          },
+          prepare: (payload: string) => ({
+            payload,
+            meta: payload.length,
+          }),
+        },
+      },
+    })
+
+    expectTypeOf(
+      counter.actions.incrementByStrLen('test').type,
+    ).toEqualTypeOf<'test/incrementByStrLen'>()
+
+    expectTypeOf(counter.actions.incrementByStrLen('test').payload).toBeNumber()
+
+    expectTypeOf(counter.actions.concatMetaStrLen('test').payload).toBeString()
+
+    expectTypeOf(counter.actions.concatMetaStrLen('test').meta).toBeNumber()
+
+    expectTypeOf(
+      counter.actions.incrementByStrLen('test').payload,
+    ).not.toBeString()
+
+    expectTypeOf(counter.actions.concatMetaStrLen('test').meta).not.toBeString()
+  })
+
+  test('access meta and error from reducer', () => {
+    const counter = createSlice({
+      name: 'test',
+      initialState: { counter: 0, concat: '' },
+      reducers: {
+        // case: meta and error not used in reducer
+        testDefaultMetaAndError: {
+          reducer(_, action: PayloadAction<number, string>) {},
+          prepare: (payload: number) => ({
+            payload,
+            meta: 'meta' as 'meta',
+            error: 'error' as 'error',
+          }),
+        },
+        // case: meta and error marked as "unknown" in reducer
+        testUnknownMetaAndError: {
+          reducer(
+            _,
+            action: PayloadAction<number, string, unknown, unknown>,
+          ) {},
+          prepare: (payload: number) => ({
+            payload,
+            meta: 'meta' as 'meta',
+            error: 'error' as 'error',
+          }),
+        },
+        // case: meta and error are typed in the reducer as returned by prepare
+        testMetaAndError: {
+          reducer(_, action: PayloadAction<number, string, 'meta', 'error'>) {},
+          prepare: (payload: number) => ({
+            payload,
+            meta: 'meta' as 'meta',
+            error: 'error' as 'error',
+          }),
+        },
+        // case: meta is typed differently in the reducer than returned from prepare
+        testErroneousMeta: {
+          reducer(_, action: PayloadAction<number, string, 'meta', 'error'>) {},
+          // @ts-expect-error
+          prepare: (payload: number) => ({
+            payload,
+            meta: 1,
+            error: 'error' as 'error',
+          }),
+        },
+        // case: error is typed differently in the reducer than returned from prepare
+        testErroneousError: {
+          reducer(_, action: PayloadAction<number, string, 'meta', 'error'>) {},
+          // @ts-expect-error
+          prepare: (payload: number) => ({
+            payload,
+            meta: 'meta' as 'meta',
+            error: 1,
+          }),
+        },
+      },
+    })
+  })
+
+  test('returned case reducer has the correct type', () => {
+    const counter = createSlice({
+      name: 'counter',
+      initialState: 0,
+      reducers: {
+        increment(state, action: PayloadAction<number>) {
+          return state + action.payload
+        },
+        decrement: {
+          reducer(state, action: PayloadAction<number>) {
+            return state - action.payload
+          },
+          prepare(amount: number) {
+            return { payload: amount }
+          },
+        },
+      },
+    })
+
+    test('Should match positively', () => {
+      expectTypeOf(counter.caseReducers.increment).toMatchTypeOf<
+        (state: number, action: PayloadAction<number>) => number | void
+      >()
+    })
+
+    test('Should match positively for reducers with prepare callback', () => {
+      expectTypeOf(counter.caseReducers.decrement).toMatchTypeOf<
+        (state: number, action: PayloadAction<number>) => number | void
+      >()
+    })
+
+    test("Should not mismatch the payload if it's a simple reducer", () => {
+      expectTypeOf(counter.caseReducers.increment).not.toMatchTypeOf<
+        (state: number, action: PayloadAction<string>) => number | void
+      >()
+    })
+
+    test("Should not mismatch the payload if it's a reducer with a prepare callback", () => {
+      expectTypeOf(counter.caseReducers.decrement).not.toMatchTypeOf<
+        (state: number, action: PayloadAction<string>) => number | void
+      >()
+    })
+
+    test("Should not include entries that don't exist", () => {
+      expectTypeOf(counter.caseReducers).not.toHaveProperty(
+        'someThingNonExistent',
+      )
+    })
+  })
+
+  test('prepared payload does not match action payload - should cause an error.', () => {
+    const counter = createSlice({
+      name: 'counter',
+      initialState: { counter: 0 },
+      reducers: {
+        increment: {
+          reducer(state, action: PayloadAction<string>) {
+            state.counter += action.payload.length
+          },
+          // @ts-expect-error
+          prepare(x: string) {
+            return {
+              payload: 6,
+            }
+          },
+        },
+      },
+    })
+  })
+
+  test('if no Payload Type is specified, accept any payload', () => {
+    // see https://github.com/reduxjs/redux-toolkit/issues/165
+
+    const initialState = {
+      name: null,
+    }
+
+    const mySlice = createSlice({
+      name: 'name',
+      initialState,
+      reducers: {
+        setName: (state, action) => {
+          state.name = action.payload
+        },
+      },
+    })
+
+    expectTypeOf(
+      mySlice.actions.setName,
+    ).toMatchTypeOf<ActionCreatorWithNonInferrablePayload>()
+
+    const x = mySlice.actions.setName
+
+    mySlice.actions.setName(null)
+    mySlice.actions.setName('asd')
+    mySlice.actions.setName(5)
+  })
+
+  test('actions.x.match()', () => {
+    const mySlice = createSlice({
+      name: 'name',
+      initialState: { name: 'test' },
+      reducers: {
+        setName: (state, action: PayloadAction<string>) => {
+          state.name = action.payload
+        },
+      },
+    })
+
+    const x: Action<string> = {} as any
+    if (mySlice.actions.setName.match(x)) {
+      expectTypeOf(x.type).toEqualTypeOf<'name/setName'>()
+
+      expectTypeOf(x.payload).toBeString()
+    } else {
+      expectTypeOf(x.type).not.toMatchTypeOf<'name/setName'>()
+
+      expectTypeOf(x).not.toHaveProperty('payload')
+    }
+  })
+
+  test('builder callback for extraReducers', () => {
+    createSlice({
+      name: 'test',
+      initialState: 0,
+      reducers: {},
+      extraReducers: (builder) => {
+        expectTypeOf(builder).toEqualTypeOf<ActionReducerMapBuilder<number>>()
+      },
+    })
+  })
+
+  test('wrapping createSlice should be possible', () => {
+    interface GenericState<T> {
+      data?: T
+      status: 'loading' | 'finished' | 'error'
+    }
+
+    const createGenericSlice = <
+      T,
+      Reducers extends SliceCaseReducers<GenericState<T>>,
+    >({
+      name = '',
+      initialState,
+      reducers,
+    }: {
+      name: string
+      initialState: GenericState<T>
+      reducers: ValidateSliceCaseReducers<GenericState<T>, Reducers>
+    }) => {
+      return createSlice({
+        name,
+        initialState,
+        reducers: {
+          start(state) {
+            state.status = 'loading'
+          },
+          success(state: GenericState<T>, action: PayloadAction<T>) {
+            state.data = action.payload
+            state.status = 'finished'
+          },
+          ...reducers,
+        },
+      })
+    }
+
+    const wrappedSlice = createGenericSlice({
+      name: 'test',
+      initialState: { status: 'loading' } as GenericState<string>,
+      reducers: {
+        magic(state) {
+          expectTypeOf(state).toEqualTypeOf<GenericState<string>>()
+
+          expectTypeOf(state).not.toMatchTypeOf<GenericState<number>>()
+
+          state.status = 'finished'
+          state.data = 'hocus pocus'
+        },
+      },
+    })
+
+    expectTypeOf(wrappedSlice.actions.success).toMatchTypeOf<
+      ActionCreatorWithPayload<string>
+    >()
+
+    expectTypeOf(wrappedSlice.actions.magic).toMatchTypeOf<
+      ActionCreatorWithoutPayload<string>
+    >()
+  })
+
+  test('extraReducers', () => {
+    interface GenericState<T> {
+      data: T | null
+    }
+
+    function createDataSlice<
+      T,
+      Reducers extends SliceCaseReducers<GenericState<T>>,
+    >(
+      name: string,
+      reducers: ValidateSliceCaseReducers<GenericState<T>, Reducers>,
+      initialState: GenericState<T>,
+    ) {
+      const doNothing = createAction<undefined>('doNothing')
+      const setData = createAction<T>('setData')
+
+      const slice = createSlice({
+        name,
+        initialState,
+        reducers,
+        extraReducers: (builder) => {
+          builder.addCase(doNothing, (state) => {
+            return { ...state }
+          })
+          builder.addCase(setData, (state, { payload }) => {
+            return {
+              ...state,
+              data: payload,
+            }
+          })
+        },
+      })
+      return { doNothing, setData, slice }
+    }
+  })
+
+  test('slice selectors', () => {
+    const sliceWithoutSelectors = createSlice({
+      name: '',
+      initialState: '',
+      reducers: {},
+    })
+
+    expectTypeOf(sliceWithoutSelectors.selectors).not.toHaveProperty('foo')
+
+    const sliceWithSelectors = createSlice({
+      name: 'counter',
+      initialState: { value: 0 },
+      reducers: {
+        increment: (state) => {
+          state.value += 1
+        },
+      },
+      selectors: {
+        selectValue: (state) => state.value,
+        selectMultiply: (state, multiplier: number) => state.value * multiplier,
+        selectToFixed: Object.assign(
+          (state: { value: number }) => state.value.toFixed(2),
+          { static: true },
+        ),
+      },
+    })
+
+    const rootState = {
+      [sliceWithSelectors.reducerPath]: sliceWithSelectors.getInitialState(),
+    }
+
+    const { selectValue, selectMultiply, selectToFixed } =
+      sliceWithSelectors.selectors
+
+    expectTypeOf(selectValue(rootState)).toBeNumber()
+
+    expectTypeOf(selectMultiply(rootState, 2)).toBeNumber()
+
+    expectTypeOf(selectToFixed(rootState)).toBeString()
+
+    expectTypeOf(selectToFixed.unwrapped.static).toBeBoolean()
+
+    const nestedState = {
+      nested: rootState,
+    }
+
+    const nestedSelectors = sliceWithSelectors.getSelectors(
+      (rootState: typeof nestedState) => rootState.nested.counter,
+    )
+
+    expectTypeOf(nestedSelectors.selectValue(nestedState)).toBeNumber()
+
+    expectTypeOf(nestedSelectors.selectMultiply(nestedState, 2)).toBeNumber()
+
+    expectTypeOf(nestedSelectors.selectToFixed(nestedState)).toBeString()
+  })
+
+  test('reducer callback', () => {
+    interface TestState {
+      foo: string
+    }
+
+    interface TestArg {
+      test: string
+    }
+
+    interface TestReturned {
+      payload: string
+    }
+
+    interface TestReject {
+      cause: string
+    }
+
+    const slice = createSlice({
+      name: 'test',
+      initialState: {} as TestState,
+      reducers: (create) => {
+        const preTypedAsyncThunk = create.asyncThunk.withTypes<{
+          rejectValue: TestReject
+        }>()
+
+        // @ts-expect-error
+        create.asyncThunk<any, any, { state: StoreState }>(() => {})
+
+        // @ts-expect-error
+        create.asyncThunk.withTypes<{
+          rejectValue: string
+          dispatch: StoreDispatch
+        }>()
+
+        return {
+          normalReducer: create.reducer<string>((state, action) => {
+            expectTypeOf(state).toEqualTypeOf<TestState>()
+
+            expectTypeOf(action.payload).toBeString()
+          }),
+          optionalReducer: create.reducer<string | undefined>(
+            (state, action) => {
+              expectTypeOf(state).toEqualTypeOf<TestState>()
+
+              expectTypeOf(action.payload).toEqualTypeOf<string | undefined>()
+            },
+          ),
+          noActionReducer: create.reducer((state) => {
+            expectTypeOf(state).toEqualTypeOf<TestState>()
+          }),
+          preparedReducer: create.preparedReducer(
+            (payload: string) => ({
+              payload,
+              meta: 'meta' as const,
+              error: 'error' as const,
+            }),
+            (state, action) => {
+              expectTypeOf(state).toEqualTypeOf<TestState>()
+
+              expectTypeOf(action.payload).toBeString()
+
+              expectTypeOf(action.meta).toEqualTypeOf<'meta'>()
+
+              expectTypeOf(action.error).toEqualTypeOf<'error'>()
+            },
+          ),
+          testInferVoid: create.asyncThunk(() => {}, {
+            pending(state, action) {
+              expectTypeOf(state).toEqualTypeOf<TestState>()
+
+              expectTypeOf(action.meta.arg).toBeVoid()
+            },
+            fulfilled(state, action) {
+              expectTypeOf(state).toEqualTypeOf<TestState>()
+
+              expectTypeOf(action.meta.arg).toBeVoid()
+
+              expectTypeOf(action.payload).toBeVoid()
+            },
+            rejected(state, action) {
+              expectTypeOf(state).toEqualTypeOf<TestState>()
+
+              expectTypeOf(action.meta.arg).toBeVoid()
+
+              expectTypeOf(action.error).toEqualTypeOf<SerializedError>()
+            },
+            settled(state, action) {
+              expectTypeOf(state).toEqualTypeOf<TestState>()
+
+              expectTypeOf(action.meta.arg).toBeVoid()
+
+              if (isRejected(action)) {
+                expectTypeOf(action.error).toEqualTypeOf<SerializedError>()
+              } else {
+                expectTypeOf(action.payload).toBeVoid()
+              }
+            },
+          }),
+          testInfer: create.asyncThunk(
+            function payloadCreator(arg: TestArg, api) {
+              return Promise.resolve<TestReturned>({ payload: 'foo' })
+            },
+            {
+              pending(state, action) {
+                expectTypeOf(state).toEqualTypeOf<TestState>()
+
+                expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
+              },
+              fulfilled(state, action) {
+                expectTypeOf(state).toEqualTypeOf<TestState>()
+
+                expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
+
+                expectTypeOf(action.payload).toEqualTypeOf<TestReturned>()
+              },
+              rejected(state, action) {
+                expectTypeOf(state).toEqualTypeOf<TestState>()
+
+                expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
+
+                expectTypeOf(action.error).toEqualTypeOf<SerializedError>()
+              },
+              settled(state, action) {
+                expectTypeOf(state).toEqualTypeOf<TestState>()
+
+                expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
+
+                if (isRejected(action)) {
+                  expectTypeOf(action.error).toEqualTypeOf<SerializedError>()
+                } else {
+                  expectTypeOf(action.payload).toEqualTypeOf<TestReturned>()
+                }
+              },
+            },
+          ),
+          testExplicitType: create.asyncThunk<
+            TestReturned,
+            TestArg,
+            {
+              rejectValue: TestReject
+            }
+          >(
+            function payloadCreator(arg, api) {
+              // here would be a circular reference
+              expectTypeOf(api.getState()).toBeUnknown()
+              // here would be a circular reference
+              expectTypeOf(api.dispatch).toMatchTypeOf<
+                ThunkDispatch<any, any, any>
+              >()
+
+              // so you need to cast inside instead
+              const getState = api.getState as () => StoreState
+              const dispatch = api.dispatch as StoreDispatch
+
+              expectTypeOf(arg).toEqualTypeOf<TestArg>()
+
+              expectTypeOf(api.rejectWithValue).toMatchTypeOf<
+                (value: TestReject) => any
+              >()
+
+              return Promise.resolve({ payload: 'foo' })
+            },
+            {
+              pending(state, action) {
+                expectTypeOf(state).toEqualTypeOf<TestState>()
+
+                expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
+              },
+              fulfilled(state, action) {
+                expectTypeOf(state).toEqualTypeOf<TestState>()
+
+                expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
+
+                expectTypeOf(action.payload).toEqualTypeOf<TestReturned>()
+              },
+              rejected(state, action) {
+                expectTypeOf(state).toEqualTypeOf<TestState>()
+
+                expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
+
+                expectTypeOf(action.error).toEqualTypeOf<SerializedError>()
+
+                expectTypeOf(action.payload).toEqualTypeOf<
+                  TestReject | undefined
+                >()
+              },
+              settled(state, action) {
+                expectTypeOf(state).toEqualTypeOf<TestState>()
+
+                expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
+
+                if (isRejected(action)) {
+                  expectTypeOf(action.error).toEqualTypeOf<SerializedError>()
+
+                  expectTypeOf(action.payload).toEqualTypeOf<
+                    TestReject | undefined
+                  >()
+                } else {
+                  expectTypeOf(action.payload).toEqualTypeOf<TestReturned>()
+                }
+              },
+            },
+          ),
+          testPreTyped: preTypedAsyncThunk(
+            function payloadCreator(arg: TestArg, api) {
+              expectTypeOf(api.rejectWithValue).toMatchTypeOf<
+                (value: TestReject) => any
+              >()
+
+              return Promise.resolve<TestReturned>({ payload: 'foo' })
+            },
+            {
+              pending(state, action) {
+                expectTypeOf(state).toEqualTypeOf<TestState>()
+
+                expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
+              },
+              fulfilled(state, action) {
+                expectTypeOf(state).toEqualTypeOf<TestState>()
+
+                expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
+
+                expectTypeOf(action.payload).toEqualTypeOf<TestReturned>()
+              },
+              rejected(state, action) {
+                expectTypeOf(state).toEqualTypeOf<TestState>()
+
+                expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
+
+                expectTypeOf(action.error).toEqualTypeOf<SerializedError>()
+
+                expectTypeOf(action.payload).toEqualTypeOf<
+                  TestReject | undefined
+                >()
+              },
+              settled(state, action) {
+                expectTypeOf(state).toEqualTypeOf<TestState>()
+
+                expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
+
+                if (isRejected(action)) {
+                  expectTypeOf(action.error).toEqualTypeOf<SerializedError>()
+
+                  expectTypeOf(action.payload).toEqualTypeOf<
+                    TestReject | undefined
+                  >()
+                } else {
+                  expectTypeOf(action.payload).toEqualTypeOf<TestReturned>()
+                }
+              },
+            },
+          ),
+        }
+      },
+    })
+
+    const store = configureStore({ reducer: { test: slice.reducer } })
+
+    type StoreState = ReturnType<typeof store.getState>
+
+    type StoreDispatch = typeof store.dispatch
+
+    expectTypeOf(slice.actions.normalReducer).toMatchTypeOf<
+      PayloadActionCreator<string>
+    >()
+
+    expectTypeOf(slice.actions.normalReducer).toBeCallableWith('')
+
+    expectTypeOf(slice.actions.normalReducer).parameters.not.toMatchTypeOf<[]>()
+
+    expectTypeOf(slice.actions.normalReducer).parameters.not.toMatchTypeOf<
+      [number]
+    >()
+
+    expectTypeOf(slice.actions.optionalReducer).toMatchTypeOf<
+      ActionCreatorWithOptionalPayload<string | undefined>
+    >()
+
+    expectTypeOf(slice.actions.optionalReducer).toBeCallableWith()
+
+    expectTypeOf(slice.actions.optionalReducer).toBeCallableWith('')
+
+    expectTypeOf(slice.actions.optionalReducer).parameter(0).not.toBeNumber()
+
+    expectTypeOf(
+      slice.actions.noActionReducer,
+    ).toMatchTypeOf<ActionCreatorWithoutPayload>()
+
+    expectTypeOf(slice.actions.noActionReducer).toBeCallableWith()
+
+    expectTypeOf(slice.actions.noActionReducer).parameter(0).not.toBeString()
+
+    expectTypeOf(slice.actions.preparedReducer).toEqualTypeOf<
+      ActionCreatorWithPreparedPayload<
+        [string],
+        string,
+        'test/preparedReducer',
+        'error',
+        'meta'
+      >
+    >()
+
+    expectTypeOf(slice.actions.testInferVoid).toEqualTypeOf<
+      AsyncThunk<void, void, {}>
+    >()
+
+    expectTypeOf(slice.actions.testInferVoid).toBeCallableWith()
+
+    expectTypeOf(slice.actions.testInfer).toEqualTypeOf<
+      AsyncThunk<TestReturned, TestArg, {}>
+    >()
+
+    expectTypeOf(slice.actions.testExplicitType).toEqualTypeOf<
+      AsyncThunk<TestReturned, TestArg, { rejectValue: TestReject }>
+    >()
+
+    type TestInferThunk = AsyncThunk<TestReturned, TestArg, {}>
+
+    expectTypeOf(slice.caseReducers.testInfer.pending).toEqualTypeOf<
+      CaseReducer<TestState, ReturnType<TestInferThunk['pending']>>
+    >()
+
+    expectTypeOf(slice.caseReducers.testInfer.fulfilled).toEqualTypeOf<
+      CaseReducer<TestState, ReturnType<TestInferThunk['fulfilled']>>
+    >()
+
+    expectTypeOf(slice.caseReducers.testInfer.rejected).toEqualTypeOf<
+      CaseReducer<TestState, ReturnType<TestInferThunk['rejected']>>
+    >()
+  })
+
+  test('wrapping createSlice should be possible, with callback', () => {
+    interface GenericState<T> {
+      data?: T
+      status: 'loading' | 'finished' | 'error'
+    }
+
+    const createGenericSlice = <
+      T,
+      Reducers extends SliceCaseReducers<GenericState<T>>,
+    >({
+      name = '',
+      initialState,
+      reducers,
+    }: {
+      name: string
+      initialState: GenericState<T>
+      reducers: (create: ReducerCreators<GenericState<T>>) => Reducers
+    }) => {
+      return createSlice({
+        name,
+        initialState,
+        reducers: (create) => ({
+          start: create.reducer((state) => {
+            state.status = 'loading'
+          }),
+          success: create.reducer<T>((state, action) => {
+            state.data = castDraft(action.payload)
+            state.status = 'finished'
+          }),
+          ...reducers(create),
+        }),
+      })
+    }
+
+    const wrappedSlice = createGenericSlice({
+      name: 'test',
+      initialState: { status: 'loading' } as GenericState<string>,
+      reducers: (create) => ({
+        magic: create.reducer((state) => {
+          expectTypeOf(state).toEqualTypeOf<GenericState<string>>()
+
+          expectTypeOf(state).not.toMatchTypeOf<GenericState<number>>()
+
+          state.status = 'finished'
+          state.data = 'hocus pocus'
+        }),
+      }),
+    })
+
+    expectTypeOf(wrappedSlice.actions.success).toMatchTypeOf<
+      ActionCreatorWithPayload<string>
+    >()
+
+    expectTypeOf(wrappedSlice.actions.magic).toMatchTypeOf<
+      ActionCreatorWithoutPayload<string>
+    >()
+  })
+
+  test('selectSlice', () => {
+    expectTypeOf(counterSlice.selectSlice({ counter: 0 })).toBeNumber()
+
+    // We use `not.toEqualTypeOf` instead of `not.toMatchTypeOf`
+    // because `toMatchTypeOf` allows missing properties
+    expectTypeOf(counterSlice.selectSlice).parameter(0).not.toEqualTypeOf<{}>()
+  })
+
+  test('buildCreateSlice', () => {
+    expectTypeOf(buildCreateSlice()).toEqualTypeOf(createSlice)
+
+    buildCreateSlice({
+      // @ts-expect-error not possible to recreate shape because symbol is not exported
+      creators: { asyncThunk: { [Symbol()]: createAsyncThunk } },
+    })
+    buildCreateSlice({ creators: { asyncThunk: asyncThunkCreator } })
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/createSlice.test.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/createSlice.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/createSlice.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,987 @@
+import { noop } from '@internal/listenerMiddleware/utils'
+import type { PayloadAction, WithSlice } from '@reduxjs/toolkit'
+import {
+  asyncThunkCreator,
+  buildCreateSlice,
+  combineSlices,
+  configureStore,
+  createAction,
+  createAsyncThunk,
+  createSlice,
+} from '@reduxjs/toolkit'
+
+type CreateSlice = typeof createSlice
+
+describe('createSlice', () => {
+  const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(noop)
+
+  beforeEach(() => {
+    vi.clearAllMocks()
+  })
+
+  afterAll(() => {
+    vi.restoreAllMocks()
+  })
+
+  describe('when slice is undefined', () => {
+    it('should throw an error', () => {
+      expect(() =>
+        // @ts-ignore
+        createSlice({
+          reducers: {
+            increment: (state) => state + 1,
+            multiply: (state, action: PayloadAction<number>) =>
+              state * action.payload,
+          },
+          initialState: 0,
+        }),
+      ).toThrowError()
+    })
+  })
+
+  describe('when slice is an empty string', () => {
+    it('should throw an error', () => {
+      expect(() =>
+        createSlice({
+          name: '',
+          reducers: {
+            increment: (state) => state + 1,
+            multiply: (state, action: PayloadAction<number>) =>
+              state * action.payload,
+          },
+          initialState: 0,
+        }),
+      ).toThrowError()
+    })
+  })
+
+  describe('when initial state is undefined', () => {
+    beforeEach(() => {
+      vi.stubEnv('NODE_ENV', 'development')
+    })
+
+    afterEach(() => {
+      vi.unstubAllEnvs()
+    })
+
+    it('should throw an error', () => {
+      createSlice({
+        name: 'test',
+        reducers: {},
+        initialState: undefined,
+      })
+
+      expect(consoleErrorSpy).toHaveBeenCalledOnce()
+
+      expect(consoleErrorSpy).toHaveBeenLastCalledWith(
+        'You must provide an `initialState` value that is not `undefined`. You may have misspelled `initialState`',
+      )
+    })
+  })
+
+  describe('when passing slice', () => {
+    const { actions, reducer, caseReducers } = createSlice({
+      reducers: {
+        increment: (state) => state + 1,
+      },
+      initialState: 0,
+      name: 'cool',
+    })
+
+    it('should create increment action', () => {
+      expect(actions.hasOwnProperty('increment')).toBe(true)
+    })
+
+    it('should have the correct action for increment', () => {
+      expect(actions.increment()).toEqual({
+        type: 'cool/increment',
+        payload: undefined,
+      })
+    })
+
+    it('should return the correct value from reducer', () => {
+      expect(reducer(undefined, actions.increment())).toEqual(1)
+    })
+
+    it('should include the generated case reducers', () => {
+      expect(caseReducers).toBeTruthy()
+      expect(caseReducers.increment).toBeTruthy()
+      expect(typeof caseReducers.increment).toBe('function')
+    })
+
+    it('getInitialState should return the state', () => {
+      const initialState = 42
+      const slice = createSlice({
+        name: 'counter',
+        initialState,
+        reducers: {},
+      })
+
+      expect(slice.getInitialState()).toBe(initialState)
+    })
+
+    it('should allow non-draftable initial state', () => {
+      expect(() =>
+        createSlice({
+          name: 'params',
+          initialState: new URLSearchParams(),
+          reducers: {},
+        }),
+      ).not.toThrowError()
+    })
+  })
+
+  describe('when initialState is a function', () => {
+    const initialState = () => ({ user: '' })
+
+    const { actions, reducer } = createSlice({
+      reducers: {
+        setUserName: (state, action) => {
+          state.user = action.payload
+        },
+      },
+      initialState,
+      name: 'user',
+    })
+
+    it('should set the username', () => {
+      expect(reducer(undefined, actions.setUserName('eric'))).toEqual({
+        user: 'eric',
+      })
+    })
+
+    it('getInitialState should return the state', () => {
+      const initialState = () => 42
+      const slice = createSlice({
+        name: 'counter',
+        initialState,
+        reducers: {},
+      })
+
+      expect(slice.getInitialState()).toBe(42)
+    })
+
+    it('should allow non-draftable initial state', () => {
+      expect(() =>
+        createSlice({
+          name: 'params',
+          initialState: () => new URLSearchParams(),
+          reducers: {},
+        }),
+      ).not.toThrowError()
+    })
+  })
+
+  describe('when mutating state object', () => {
+    const initialState = { user: '' }
+
+    const { actions, reducer } = createSlice({
+      reducers: {
+        setUserName: (state, action) => {
+          state.user = action.payload
+        },
+      },
+      initialState,
+      name: 'user',
+    })
+
+    it('should set the username', () => {
+      expect(reducer(initialState, actions.setUserName('eric'))).toEqual({
+        user: 'eric',
+      })
+    })
+  })
+
+  describe('when passing extra reducers', () => {
+    const addMore = createAction<{ amount: number }>('ADD_MORE')
+
+    const { reducer } = createSlice({
+      name: 'test',
+      reducers: {
+        increment: (state) => state + 1,
+        multiply: (state, action) => state * action.payload,
+      },
+      extraReducers: (builder) => {
+        builder.addCase(
+          addMore,
+          (state, action) => state + action.payload.amount,
+        )
+      },
+
+      initialState: 0,
+    })
+
+    it('should call extra reducers when their actions are dispatched', () => {
+      const result = reducer(10, addMore({ amount: 5 }))
+
+      expect(result).toBe(15)
+    })
+
+    describe('builder callback for extraReducers', () => {
+      const increment = createAction<number, 'increment'>('increment')
+
+      test('can be used with actionCreators', () => {
+        const slice = createSlice({
+          name: 'counter',
+          initialState: 0,
+          reducers: {},
+          extraReducers: (builder) =>
+            builder.addCase(
+              increment,
+              (state, action) => state + action.payload,
+            ),
+        })
+        expect(slice.reducer(0, increment(5))).toBe(5)
+      })
+
+      test('can be used with string action types', () => {
+        const slice = createSlice({
+          name: 'counter',
+          initialState: 0,
+          reducers: {},
+          extraReducers: (builder) =>
+            builder.addCase(
+              'increment',
+              (state, action: { type: 'increment'; payload: number }) =>
+                state + action.payload,
+            ),
+        })
+        expect(slice.reducer(0, increment(5))).toBe(5)
+      })
+
+      test('prevents the same action type from being specified twice', () => {
+        expect(() => {
+          const slice = createSlice({
+            name: 'counter',
+            initialState: 0,
+            reducers: {},
+            extraReducers: (builder) =>
+              builder
+                .addCase('increment', (state) => state + 1)
+                .addCase('increment', (state) => state + 1),
+          })
+          slice.reducer(undefined, { type: 'unrelated' })
+        }).toThrowErrorMatchingInlineSnapshot(
+          `[Error: \`builder.addCase\` cannot be called with two reducers for the same action type 'increment']`,
+        )
+      })
+
+      test('can be used with addAsyncThunk and async thunks', () => {
+        const asyncThunk = createAsyncThunk('test', (n: number) => n)
+        const slice = createSlice({
+          name: 'counter',
+          initialState: {
+            loading: false,
+            errored: false,
+            value: 0,
+          },
+          reducers: {},
+          extraReducers: (builder) =>
+            builder.addAsyncThunk(asyncThunk, {
+              pending(state) {
+                state.loading = true
+              },
+              fulfilled(state, action) {
+                state.value = action.payload
+              },
+              rejected(state) {
+                state.errored = true
+              },
+              settled(state) {
+                state.loading = false
+              },
+            }),
+        })
+        expect(
+          slice.reducer(undefined, asyncThunk.pending('requestId', 5)),
+        ).toEqual({
+          loading: true,
+          errored: false,
+          value: 0,
+        })
+        expect(
+          slice.reducer(undefined, asyncThunk.fulfilled(5, 'requestId', 5)),
+        ).toEqual({
+          loading: false,
+          errored: false,
+          value: 5,
+        })
+        expect(
+          slice.reducer(
+            undefined,
+            asyncThunk.rejected(new Error(), 'requestId', 5),
+          ),
+        ).toEqual({
+          loading: false,
+          errored: true,
+          value: 0,
+        })
+      })
+
+      test('can be used with addMatcher and type guard functions', () => {
+        const slice = createSlice({
+          name: 'counter',
+          initialState: 0,
+          reducers: {},
+          extraReducers: (builder) =>
+            builder.addMatcher(
+              increment.match,
+              (state, action: { type: 'increment'; payload: number }) =>
+                state + action.payload,
+            ),
+        })
+        expect(slice.reducer(0, increment(5))).toBe(5)
+      })
+
+      test('can be used with addDefaultCase', () => {
+        const slice = createSlice({
+          name: 'counter',
+          initialState: 0,
+          reducers: {},
+          extraReducers: (builder) =>
+            builder.addDefaultCase(
+              (state, action) =>
+                state + (action as PayloadAction<number>).payload,
+            ),
+        })
+        expect(slice.reducer(0, increment(5))).toBe(5)
+      })
+
+      // for further tests, see the test of createReducer that goes way more into depth on this
+    })
+  })
+
+  describe('behavior with enhanced case reducers', () => {
+    it('should pass all arguments to the prepare function', () => {
+      const prepare = vi.fn((payload, somethingElse) => ({ payload }))
+
+      const testSlice = createSlice({
+        name: 'test',
+        initialState: 0,
+        reducers: {
+          testReducer: {
+            reducer: (s) => s,
+            prepare,
+          },
+        },
+      })
+
+      expect(testSlice.actions.testReducer('a', 1)).toEqual({
+        type: 'test/testReducer',
+        payload: 'a',
+      })
+      expect(prepare).toHaveBeenCalledWith('a', 1)
+    })
+
+    it('should call the reducer function', () => {
+      const reducer = vi.fn(() => 5)
+
+      const testSlice = createSlice({
+        name: 'test',
+        initialState: 0,
+        reducers: {
+          testReducer: {
+            reducer,
+            prepare: (payload: any) => ({ payload }),
+          },
+        },
+      })
+
+      testSlice.reducer(0, testSlice.actions.testReducer('testPayload'))
+      expect(reducer).toHaveBeenCalledWith(
+        0,
+        expect.objectContaining({ payload: 'testPayload' }),
+      )
+    })
+  })
+
+  describe('circularity', () => {
+    test('extraReducers can reference each other circularly', () => {
+      const first = createSlice({
+        name: 'first',
+        initialState: 'firstInitial',
+        reducers: {
+          something() {
+            return 'firstSomething'
+          },
+        },
+        extraReducers(builder) {
+          // eslint-disable-next-line @typescript-eslint/no-use-before-define
+          builder.addCase(second.actions.other, () => {
+            return 'firstOther'
+          })
+        },
+      })
+      const second = createSlice({
+        name: 'second',
+        initialState: 'secondInitial',
+        reducers: {
+          other() {
+            return 'secondOther'
+          },
+        },
+        extraReducers(builder) {
+          builder.addCase(first.actions.something, () => {
+            return 'secondSomething'
+          })
+        },
+      })
+
+      expect(first.reducer(undefined, { type: 'unrelated' })).toBe(
+        'firstInitial',
+      )
+      expect(first.reducer(undefined, first.actions.something())).toBe(
+        'firstSomething',
+      )
+      expect(first.reducer(undefined, second.actions.other())).toBe(
+        'firstOther',
+      )
+
+      expect(second.reducer(undefined, { type: 'unrelated' })).toBe(
+        'secondInitial',
+      )
+      expect(second.reducer(undefined, first.actions.something())).toBe(
+        'secondSomething',
+      )
+      expect(second.reducer(undefined, second.actions.other())).toBe(
+        'secondOther',
+      )
+    })
+  })
+
+  describe('Deprecation warnings', () => {
+    beforeEach(() => {
+      vi.resetModules()
+    })
+
+    afterEach(() => {
+      vi.unstubAllEnvs()
+    })
+
+    // NOTE: This needs to be in front of the later `createReducer` call to check the one-time warning
+    it('Throws an error if the legacy object notation is used', async () => {
+      const { createSlice } = await import('../createSlice')
+
+      let dummySlice = (createSlice as CreateSlice)({
+        name: 'dummy',
+        initialState: [],
+        reducers: {},
+        extraReducers: {
+          // @ts-ignore
+          a: () => [],
+        },
+      })
+      let reducer: any
+      // Have to trigger the lazy creation
+      const wrapper = () => {
+        reducer = dummySlice.reducer
+        reducer(undefined, { type: 'dummy' })
+      }
+
+      expect(wrapper).toThrowError(
+        /The object notation for `createSlice.extraReducers` has been removed/,
+      )
+
+      dummySlice = (createSlice as CreateSlice)({
+        name: 'dummy',
+        initialState: [],
+        reducers: {},
+        extraReducers: {
+          // @ts-ignore
+          a: () => [],
+        },
+      })
+      expect(wrapper).toThrowError(
+        /The object notation for `createSlice.extraReducers` has been removed/,
+      )
+    })
+
+    // TODO Determine final production behavior here
+    it.todo('Crashes in production', () => {
+      vi.stubEnv('NODE_ENV', 'production')
+
+      const { createSlice } = require('../createSlice')
+
+      const dummySlice = (createSlice as CreateSlice)({
+        name: 'dummy',
+        initialState: [],
+        reducers: {},
+        // @ts-ignore
+        extraReducers: {},
+      })
+      const wrapper = () => {
+        const { reducer } = dummySlice
+        reducer(undefined, { type: 'dummy' })
+      }
+
+      expect(wrapper).toThrowError(
+        /The object notation for `createSlice.extraReducers` has been removed/,
+      )
+
+      vi.unstubAllEnvs()
+    })
+  })
+  describe('slice selectors', () => {
+    const slice = createSlice({
+      name: 'counter',
+      initialState: 42,
+      reducers: {},
+      selectors: {
+        selectSlice: (state) => state,
+        selectMultiple: Object.assign(
+          (state: number, multiplier: number) => state * multiplier,
+          { test: 0 },
+        ),
+      },
+    })
+    it('expects reducer under slice.reducerPath if no selectState callback passed', () => {
+      const testState = {
+        [slice.reducerPath]: slice.getInitialState(),
+      }
+      const { selectSlice, selectMultiple } = slice.selectors
+      expect(selectSlice(testState)).toBe(slice.getInitialState())
+      expect(selectMultiple(testState, 2)).toBe(slice.getInitialState() * 2)
+    })
+    it('allows passing a selector for a custom location', () => {
+      const customState = {
+        number: slice.getInitialState(),
+      }
+      const { selectSlice, selectMultiple } = slice.getSelectors(
+        (state: typeof customState) => state.number,
+      )
+      expect(selectSlice(customState)).toBe(slice.getInitialState())
+      expect(selectMultiple(customState, 2)).toBe(slice.getInitialState() * 2)
+    })
+    it('allows accessing properties on the selector', () => {
+      expect(slice.selectors.selectMultiple.unwrapped.test).toBe(0)
+    })
+    it('has selectSlice attached to slice, which can go without this', () => {
+      const slice = createSlice({
+        name: 'counter',
+        initialState: 42,
+        reducers: {},
+      })
+      const { selectSlice } = slice
+      expect(() => selectSlice({ counter: 42 })).not.toThrow()
+      expect(selectSlice({ counter: 42 })).toBe(42)
+    })
+  })
+  describe('slice injections', () => {
+    it('uses injectInto to inject slice into combined reducer', () => {
+      const slice = createSlice({
+        name: 'counter',
+        initialState: 42,
+        reducers: {
+          increment: (state) => ++state,
+        },
+        selectors: {
+          selectMultiple: (state, multiplier: number) => state * multiplier,
+        },
+      })
+
+      const { increment } = slice.actions
+
+      const combinedReducer = combineSlices({
+        static: slice.reducer,
+      }).withLazyLoadedSlices<WithSlice<typeof slice>>()
+
+      const uninjectedState = combinedReducer(undefined, increment())
+
+      expect(uninjectedState.counter).toBe(undefined)
+
+      const injectedSlice = slice.injectInto(combinedReducer)
+
+      // selector returns initial state if undefined in real state
+      expect(injectedSlice.selectSlice(uninjectedState)).toBe(
+        slice.getInitialState(),
+      )
+      expect(injectedSlice.selectors.selectMultiple({}, 1)).toBe(
+        slice.getInitialState(),
+      )
+      expect(injectedSlice.getSelectors().selectMultiple(undefined, 1)).toBe(
+        slice.getInitialState(),
+      )
+
+      const injectedState = combinedReducer(undefined, increment())
+
+      expect(injectedSlice.selectSlice(injectedState)).toBe(
+        slice.getInitialState() + 1,
+      )
+      expect(injectedSlice.selectors.selectMultiple(injectedState, 1)).toBe(
+        slice.getInitialState() + 1,
+      )
+    })
+    it('allows providing a custom name to inject under', () => {
+      const slice = createSlice({
+        name: 'counter',
+        reducerPath: 'injected',
+        initialState: 42,
+        reducers: {
+          increment: (state) => ++state,
+        },
+        selectors: {
+          selectMultiple: (state, multiplier: number) => state * multiplier,
+        },
+      })
+
+      const { increment } = slice.actions
+
+      const combinedReducer = combineSlices({
+        static: slice.reducer,
+      }).withLazyLoadedSlices<WithSlice<typeof slice> & { injected2: number }>()
+
+      const uninjectedState = combinedReducer(undefined, increment())
+
+      expect(uninjectedState.injected).toBe(undefined)
+
+      const injected = slice.injectInto(combinedReducer)
+
+      const injectedState = combinedReducer(undefined, increment())
+
+      expect(injected.selectSlice(injectedState)).toBe(
+        slice.getInitialState() + 1,
+      )
+      expect(injected.selectors.selectMultiple(injectedState, 2)).toBe(
+        (slice.getInitialState() + 1) * 2,
+      )
+
+      const injected2 = slice.injectInto(combinedReducer, {
+        reducerPath: 'injected2',
+      })
+
+      const injected2State = combinedReducer(undefined, increment())
+
+      expect(injected2.selectSlice(injected2State)).toBe(
+        slice.getInitialState() + 1,
+      )
+      expect(injected2.selectors.selectMultiple(injected2State, 2)).toBe(
+        (slice.getInitialState() + 1) * 2,
+      )
+    })
+    it('avoids incorrectly caching selectors', () => {
+      const slice = createSlice({
+        name: 'counter',
+        reducerPath: 'injected',
+        initialState: 42,
+        reducers: {
+          increment: (state) => ++state,
+        },
+        selectors: {
+          selectMultiple: (state, multiplier: number) => state * multiplier,
+        },
+      })
+      expect(slice.getSelectors()).toBe(slice.getSelectors())
+      const combinedReducer = combineSlices({
+        static: slice.reducer,
+      }).withLazyLoadedSlices<WithSlice<typeof slice>>()
+
+      const injected = slice.injectInto(combinedReducer)
+
+      expect(injected.getSelectors()).not.toBe(slice.getSelectors())
+
+      expect(injected.getSelectors().selectMultiple(undefined, 1)).toBe(42)
+
+      expect(() =>
+        // @ts-expect-error
+        slice.getSelectors().selectMultiple(undefined, 1),
+      ).toThrowErrorMatchingInlineSnapshot(
+        `[Error: selectState returned undefined for an uninjected slice reducer]`,
+      )
+
+      const injected2 = slice.injectInto(combinedReducer, {
+        reducerPath: 'other',
+      })
+
+      // can use same cache for localised selectors
+      expect(injected.getSelectors()).toBe(injected2.getSelectors())
+      // these should be different
+      expect(injected.selectors).not.toBe(injected2.selectors)
+    })
+    it('caches initial states for selectors', () => {
+      const slice = createSlice({
+        name: 'counter',
+        initialState: () => ({ value: 0 }),
+        reducers: {},
+        selectors: {
+          selectObj: (state) => state,
+        },
+      })
+      // not cached
+      expect(slice.getInitialState()).not.toBe(slice.getInitialState())
+      expect(slice.reducer(undefined, { type: 'dummy' })).not.toBe(
+        slice.reducer(undefined, { type: 'dummy' }),
+      )
+
+      const combinedReducer = combineSlices({
+        static: slice.reducer,
+      }).withLazyLoadedSlices<WithSlice<typeof slice>>()
+
+      const injected = slice.injectInto(combinedReducer)
+
+      // still not cached
+      expect(injected.getInitialState()).not.toBe(injected.getInitialState())
+      expect(injected.reducer(undefined, { type: 'dummy' })).not.toBe(
+        injected.reducer(undefined, { type: 'dummy' }),
+      )
+      // cached
+      expect(injected.selectSlice({})).toBe(injected.selectSlice({}))
+      expect(injected.selectors.selectObj({})).toBe(
+        injected.selectors.selectObj({}),
+      )
+    })
+  })
+  describe('reducers definition with asyncThunks', () => {
+    it('is disabled by default', () => {
+      expect(() =>
+        createSlice({
+          name: 'test',
+          initialState: [] as any[],
+          reducers: (create) => ({ thunk: create.asyncThunk(() => {}) }),
+        }),
+      ).toThrowErrorMatchingInlineSnapshot(
+        `[Error: Cannot use \`create.asyncThunk\` in the built-in \`createSlice\`. Use \`buildCreateSlice({ creators: { asyncThunk: asyncThunkCreator } })\` to create a customised version of \`createSlice\`.]`,
+      )
+    })
+    const createAppSlice = buildCreateSlice({
+      creators: { asyncThunk: asyncThunkCreator },
+    })
+    function pending(state: any[], action: any) {
+      state.push(['pendingReducer', action])
+    }
+    function fulfilled(state: any[], action: any) {
+      state.push(['fulfilledReducer', action])
+    }
+    function rejected(state: any[], action: any) {
+      state.push(['rejectedReducer', action])
+    }
+    function settled(state: any[], action: any) {
+      state.push(['settledReducer', action])
+    }
+
+    test('successful thunk', async () => {
+      const slice = createAppSlice({
+        name: 'test',
+        initialState: [] as any[],
+        reducers: (create) => ({
+          thunkReducers: create.asyncThunk(
+            function payloadCreator(arg: string, api) {
+              return Promise.resolve('resolved payload')
+            },
+            { pending, fulfilled, rejected, settled },
+          ),
+        }),
+      })
+
+      const store = configureStore({
+        reducer: slice.reducer,
+      })
+      await store.dispatch(slice.actions.thunkReducers('test'))
+      expect(store.getState()).toMatchObject([
+        [
+          'pendingReducer',
+          {
+            type: 'test/thunkReducers/pending',
+            payload: undefined,
+          },
+        ],
+        [
+          'fulfilledReducer',
+          {
+            type: 'test/thunkReducers/fulfilled',
+            payload: 'resolved payload',
+          },
+        ],
+        [
+          'settledReducer',
+          {
+            type: 'test/thunkReducers/fulfilled',
+            payload: 'resolved payload',
+          },
+        ],
+      ])
+    })
+
+    test('rejected thunk', async () => {
+      const slice = createAppSlice({
+        name: 'test',
+        initialState: [] as any[],
+        reducers: (create) => ({
+          thunkReducers: create.asyncThunk(
+            // payloadCreator isn't allowed to return never
+            function payloadCreator(arg: string, api): any {
+              throw new Error('')
+            },
+            { pending, fulfilled, rejected, settled },
+          ),
+        }),
+      })
+
+      const store = configureStore({
+        reducer: slice.reducer,
+      })
+      await store.dispatch(slice.actions.thunkReducers('test'))
+      expect(store.getState()).toMatchObject([
+        [
+          'pendingReducer',
+          {
+            type: 'test/thunkReducers/pending',
+            payload: undefined,
+          },
+        ],
+        [
+          'rejectedReducer',
+          {
+            type: 'test/thunkReducers/rejected',
+            payload: undefined,
+          },
+        ],
+        [
+          'settledReducer',
+          {
+            type: 'test/thunkReducers/rejected',
+            payload: undefined,
+          },
+        ],
+      ])
+    })
+
+    test('with options', async () => {
+      const slice = createAppSlice({
+        name: 'test',
+        initialState: [] as any[],
+        reducers: (create) => ({
+          thunkReducers: create.asyncThunk(
+            function payloadCreator(arg: string, api) {
+              return 'should not call this'
+            },
+            {
+              options: {
+                condition() {
+                  return false
+                },
+                dispatchConditionRejection: true,
+              },
+              pending,
+              fulfilled,
+              rejected,
+              settled,
+            },
+          ),
+        }),
+      })
+
+      const store = configureStore({
+        reducer: slice.reducer,
+      })
+      await store.dispatch(slice.actions.thunkReducers('test'))
+      expect(store.getState()).toMatchObject([
+        [
+          'rejectedReducer',
+          {
+            type: 'test/thunkReducers/rejected',
+            payload: undefined,
+            meta: { condition: true },
+          },
+        ],
+        [
+          'settledReducer',
+          {
+            type: 'test/thunkReducers/rejected',
+            payload: undefined,
+            meta: { condition: true },
+          },
+        ],
+      ])
+    })
+
+    test('has caseReducers for the asyncThunk', async () => {
+      const slice = createAppSlice({
+        name: 'test',
+        initialState: [],
+        reducers: (create) => ({
+          thunkReducers: create.asyncThunk(
+            function payloadCreator(arg, api) {
+              return Promise.resolve('resolved payload')
+            },
+            { pending, fulfilled, settled },
+          ),
+        }),
+      })
+
+      expect(slice.caseReducers.thunkReducers.pending).toBe(pending)
+      expect(slice.caseReducers.thunkReducers.fulfilled).toBe(fulfilled)
+      expect(slice.caseReducers.thunkReducers.settled).toBe(settled)
+      // even though it is not defined above, this should at least be a no-op function to match the TypeScript typings
+      // and should be callable as a reducer even if it does nothing
+      expect(() =>
+        slice.caseReducers.thunkReducers.rejected(
+          [],
+          slice.actions.thunkReducers.rejected(
+            new Error('test'),
+            'fakeRequestId',
+          ),
+        ),
+      ).not.toThrow()
+    })
+
+    test('can define reducer with prepare statement using create.preparedReducer', async () => {
+      const slice = createSlice({
+        name: 'test',
+        initialState: [] as any[],
+        reducers: (create) => ({
+          prepared: create.preparedReducer(
+            (p: string, m: number, e: { message: string }) => ({
+              payload: p,
+              meta: m,
+              error: e,
+            }),
+            (state, action) => {
+              state.push(action)
+            },
+          ),
+        }),
+      })
+
+      expect(
+        slice.reducer(
+          [],
+          slice.actions.prepared('test', 1, { message: 'err' }),
+        ),
+      ).toMatchInlineSnapshot(`
+        [
+          {
+            "error": {
+              "message": "err",
+            },
+            "meta": 1,
+            "payload": "test",
+            "type": "test/prepared",
+          },
+        ]
+      `)
+    })
+
+    test('throws an error when invoked with a normal `prepare` object that has not gone through a `create.preparedReducer` call', async () => {
+      expect(() =>
+        createSlice({
+          name: 'test',
+          initialState: [] as any[],
+          reducers: (create) => ({
+            prepared: {
+              prepare: (p: string, m: number, e: { message: string }) => ({
+                payload: p,
+                meta: m,
+                error: e,
+              }),
+              reducer: (state, action) => {
+                state.push(action)
+              },
+            },
+          }),
+        }),
+      ).toThrowErrorMatchingInlineSnapshot(
+        `[Error: Please use the \`create.preparedReducer\` notation for prepared action creators with the \`create\` notation.]`,
+      )
+    })
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/getDefaultEnhancers.test-d.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/getDefaultEnhancers.test-d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/getDefaultEnhancers.test-d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,143 @@
+import type { StoreEnhancer } from '@reduxjs/toolkit'
+import { configureStore } from '@reduxjs/toolkit'
+
+declare const enhancer1: StoreEnhancer<
+  {
+    has1: true
+  },
+  { stateHas1: true }
+>
+
+declare const enhancer2: StoreEnhancer<
+  {
+    has2: true
+  },
+  { stateHas2: true }
+>
+
+describe('type tests', () => {
+  test('prepend single element', () => {
+    const store = configureStore({
+      reducer: () => 0,
+      enhancers: (gDE) => gDE().prepend(enhancer1),
+    })
+
+    expectTypeOf(store.has1).toEqualTypeOf<true>()
+
+    expectTypeOf(store.getState().stateHas1).toEqualTypeOf<true>()
+
+    expectTypeOf(store).not.toHaveProperty('has2')
+
+    expectTypeOf(store.getState()).not.toHaveProperty('stateHas2')
+  })
+
+  test('prepend multiple (rest)', () => {
+    const store = configureStore({
+      reducer: () => 0,
+      enhancers: (gDE) => gDE().prepend(enhancer1, enhancer2),
+    })
+
+    expectTypeOf(store.has1).toEqualTypeOf<true>()
+
+    expectTypeOf(store.getState().stateHas1).toEqualTypeOf<true>()
+
+    expectTypeOf(store.has2).toEqualTypeOf<true>()
+
+    expectTypeOf(store.getState().stateHas2).toEqualTypeOf<true>()
+
+    expectTypeOf(store).not.toHaveProperty('has3')
+
+    expectTypeOf(store.getState()).not.toHaveProperty('stateHas3')
+  })
+
+  test('prepend multiple (array notation)', () => {
+    const store = configureStore({
+      reducer: () => 0,
+      enhancers: (gDE) => gDE().prepend([enhancer1, enhancer2] as const),
+    })
+
+    expectTypeOf(store.has1).toEqualTypeOf<true>()
+
+    expectTypeOf(store.getState().stateHas1).toEqualTypeOf<true>()
+
+    expectTypeOf(store.has2).toEqualTypeOf<true>()
+
+    expectTypeOf(store.getState().stateHas2).toEqualTypeOf<true>()
+
+    expectTypeOf(store).not.toHaveProperty('has3')
+
+    expectTypeOf(store.getState()).not.toHaveProperty('stateHas3')
+  })
+
+  test('concat single element', () => {
+    const store = configureStore({
+      reducer: () => 0,
+      enhancers: (gDE) => gDE().concat(enhancer1),
+    })
+
+    expectTypeOf(store.has1).toEqualTypeOf<true>()
+
+    expectTypeOf(store.getState().stateHas1).toEqualTypeOf<true>()
+
+    expectTypeOf(store).not.toHaveProperty('has2')
+
+    expectTypeOf(store.getState()).not.toHaveProperty('stateHas2')
+  })
+
+  test('prepend multiple (rest)', () => {
+    const store = configureStore({
+      reducer: () => 0,
+      enhancers: (gDE) => gDE().concat(enhancer1, enhancer2),
+    })
+
+    expectTypeOf(store.has1).toEqualTypeOf<true>()
+
+    expectTypeOf(store.getState().stateHas1).toEqualTypeOf<true>()
+
+    expectTypeOf(store.has2).toEqualTypeOf<true>()
+
+    expectTypeOf(store.getState().stateHas2).toEqualTypeOf<true>()
+
+    expectTypeOf(store).not.toHaveProperty('has3')
+
+    expectTypeOf(store.getState()).not.toHaveProperty('stateHas3')
+  })
+
+  test('concat multiple (array notation)', () => {
+    const store = configureStore({
+      reducer: () => 0,
+      enhancers: (gDE) => gDE().concat([enhancer1, enhancer2] as const),
+    })
+
+    expectTypeOf(store.has1).toEqualTypeOf<true>()
+
+    expectTypeOf(store.getState().stateHas1).toEqualTypeOf<true>()
+
+    expectTypeOf(store.has2).toEqualTypeOf<true>()
+
+    expectTypeOf(store.getState().stateHas2).toEqualTypeOf<true>()
+
+    expectTypeOf(store).not.toHaveProperty('has3')
+
+    expectTypeOf(store.getState()).not.toHaveProperty('stateHas3')
+  })
+
+  test('concat and prepend', () => {
+    const store = configureStore({
+      reducer: () => 0,
+      enhancers: (gDE) => gDE().concat(enhancer1).prepend(enhancer2),
+    })
+
+    expectTypeOf(store.has1).toEqualTypeOf<true>()
+
+    expectTypeOf(store.getState().stateHas1).toEqualTypeOf<true>()
+
+    expectTypeOf(store.has2).toEqualTypeOf<true>()
+
+    expectTypeOf(store.getState().stateHas2).toEqualTypeOf<true>()
+
+    expectTypeOf(store).not.toHaveProperty('has3')
+
+    expectTypeOf(store.getState()).not.toHaveProperty('stateHas3')
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/getDefaultMiddleware.test-d.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/getDefaultMiddleware.test-d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/getDefaultMiddleware.test-d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,199 @@
+import { buildGetDefaultMiddleware } from '@internal/getDefaultMiddleware'
+import type {
+  Action,
+  Dispatch,
+  Middleware,
+  ThunkAction,
+  ThunkDispatch,
+  ThunkMiddleware,
+  Tuple,
+  UnknownAction,
+} from '@reduxjs/toolkit'
+import { configureStore } from '@reduxjs/toolkit'
+
+declare const middleware1: Middleware<{
+  (_: string): number
+}>
+
+declare const middleware2: Middleware<{
+  (_: number): string
+}>
+
+type ThunkReturn = Promise<'thunk'>
+declare const thunkCreator: () => () => ThunkReturn
+
+const getDefaultMiddleware = buildGetDefaultMiddleware()
+
+describe('type tests', () => {
+  test('prepend single element', () => {
+    const store = configureStore({
+      reducer: () => 0,
+      middleware: (gDM) => gDM().prepend(middleware1),
+    })
+
+    expectTypeOf(store.dispatch('foo')).toBeNumber()
+
+    expectTypeOf(store.dispatch(thunkCreator())).toEqualTypeOf<ThunkReturn>()
+
+    expectTypeOf(store.dispatch('foo')).not.toBeString()
+  })
+
+  test('prepend multiple (rest)', () => {
+    const store = configureStore({
+      reducer: () => 0,
+      middleware: (gDM) => gDM().prepend(middleware1, middleware2),
+    })
+
+    expectTypeOf(store.dispatch('foo')).toBeNumber()
+
+    expectTypeOf(store.dispatch(5)).toBeString()
+
+    expectTypeOf(store.dispatch(thunkCreator())).toEqualTypeOf<ThunkReturn>()
+
+    expectTypeOf(store.dispatch('foo')).not.toBeString()
+  })
+
+  test('prepend multiple (array notation)', () => {
+    const store = configureStore({
+      reducer: () => 0,
+      middleware: (gDM) => gDM().prepend([middleware1, middleware2] as const),
+    })
+
+    expectTypeOf(store.dispatch('foo')).toBeNumber()
+
+    expectTypeOf(store.dispatch(5)).toBeString()
+
+    expectTypeOf(store.dispatch(thunkCreator())).toEqualTypeOf<ThunkReturn>()
+
+    expectTypeOf(store.dispatch('foo')).not.toBeString()
+  })
+
+  test('concat single element', () => {
+    const store = configureStore({
+      reducer: () => 0,
+      middleware: (gDM) => gDM().concat(middleware1),
+    })
+
+    expectTypeOf(store.dispatch('foo')).toBeNumber()
+
+    expectTypeOf(store.dispatch(thunkCreator())).toEqualTypeOf<ThunkReturn>()
+
+    expectTypeOf(store.dispatch('foo')).not.toBeString()
+  })
+
+  test('prepend multiple (rest)', () => {
+    const store = configureStore({
+      reducer: () => 0,
+      middleware: (gDM) => gDM().concat(middleware1, middleware2),
+    })
+
+    expectTypeOf(store.dispatch('foo')).toBeNumber()
+
+    expectTypeOf(store.dispatch(5)).toBeString()
+
+    expectTypeOf(store.dispatch(thunkCreator())).toEqualTypeOf<ThunkReturn>()
+
+    expectTypeOf(store.dispatch('foo')).not.toBeString()
+  })
+
+  test('concat multiple (array notation)', () => {
+    const store = configureStore({
+      reducer: () => 0,
+      middleware: (gDM) => gDM().concat([middleware1, middleware2] as const),
+    })
+
+    expectTypeOf(store.dispatch('foo')).toBeNumber()
+
+    expectTypeOf(store.dispatch(5)).toBeString()
+
+    expectTypeOf(store.dispatch(thunkCreator())).toEqualTypeOf<ThunkReturn>()
+
+    expectTypeOf(store.dispatch('foo')).not.toBeString()
+  })
+
+  test('concat and prepend', () => {
+    const store = configureStore({
+      reducer: () => 0,
+      middleware: (gDM) => gDM().concat(middleware1).prepend(middleware2),
+    })
+
+    expectTypeOf(store.dispatch('foo')).toBeNumber()
+
+    expectTypeOf(store.dispatch(5)).toBeString()
+
+    expectTypeOf(store.dispatch(thunkCreator())).toEqualTypeOf<ThunkReturn>()
+
+    expectTypeOf(store.dispatch('foo')).not.toBeString()
+  })
+
+  test('allows passing options to thunk', () => {
+    const extraArgument = 42 as const
+
+    const m2 = getDefaultMiddleware({
+      thunk: false,
+    })
+
+    expectTypeOf(m2).toMatchTypeOf<Tuple<[]>>()
+
+    const dummyMiddleware: Middleware<
+      {
+        (action: Action<'actionListenerMiddleware/add'>): () => void
+      },
+      { counter: number }
+    > = (storeApi) => (next) => (action) => {
+      return next(action)
+    }
+
+    const dummyMiddleware2: Middleware<{}, { counter: number }> =
+      (storeApi) => (next) => (action) => {}
+
+    const testThunk: ThunkAction<
+      void,
+      { counter: number },
+      number,
+      UnknownAction
+    > = (dispatch, getState, extraArg) => {
+      expect(extraArg).toBe(extraArgument)
+    }
+
+    const reducer = () => ({ counter: 123 })
+
+    const store = configureStore({
+      reducer,
+      middleware: (gDM) => {
+        const middleware = gDM({
+          thunk: { extraArgument },
+          immutableCheck: false,
+          serializableCheck: false,
+          actionCreatorCheck: false,
+        })
+
+        const m3 = middleware.concat(dummyMiddleware, dummyMiddleware2)
+
+        expectTypeOf(m3).toMatchTypeOf<
+          Tuple<
+            [
+              ThunkMiddleware<any, UnknownAction, 42>,
+              Middleware<
+                (action: Action<'actionListenerMiddleware/add'>) => () => void,
+                {
+                  counter: number
+                },
+                Dispatch<UnknownAction>
+              >,
+              Middleware<{}, any, Dispatch<UnknownAction>>,
+            ]
+          >
+        >()
+
+        return m3
+      },
+    })
+
+    expectTypeOf(store.dispatch).toMatchTypeOf<
+      ThunkDispatch<any, 42, UnknownAction> & Dispatch<UnknownAction>
+    >()
+
+    store.dispatch(testThunk)
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/getDefaultMiddleware.test.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/getDefaultMiddleware.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/getDefaultMiddleware.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,317 @@
+import { Tuple } from '@internal/utils'
+import type {
+  Action,
+  Middleware,
+  ThunkAction,
+  UnknownAction,
+} from '@reduxjs/toolkit'
+import { configureStore } from '@reduxjs/toolkit'
+import { thunk } from 'redux-thunk'
+import { vi } from 'vitest'
+
+import { buildGetDefaultMiddleware } from '@internal/getDefaultMiddleware'
+
+const getDefaultMiddleware = buildGetDefaultMiddleware()
+
+describe('getDefaultMiddleware', () => {
+  afterEach(() => {
+    vi.unstubAllEnvs()
+  })
+
+  describe('Production behavior', () => {
+    beforeEach(() => {
+      vi.resetModules()
+    })
+
+    it('returns an array with only redux-thunk in production', async () => {
+      vi.stubEnv('NODE_ENV', 'production')
+
+      const { thunk } = await import('redux-thunk')
+      const { buildGetDefaultMiddleware } = await import(
+        '@internal/getDefaultMiddleware'
+      )
+
+      const middleware = buildGetDefaultMiddleware()()
+      expect(middleware).toContain(thunk)
+      expect(middleware.length).toBe(1)
+    })
+  })
+
+  it('returns an array with additional middleware in development', () => {
+    const middleware = getDefaultMiddleware()
+    expect(middleware).toContain(thunk)
+    expect(middleware.length).toBeGreaterThan(1)
+  })
+
+  const defaultMiddleware = getDefaultMiddleware()
+
+  it('removes the thunk middleware if disabled', () => {
+    const middleware = getDefaultMiddleware({ thunk: false })
+    // @ts-ignore
+    expect(middleware.includes(thunk)).toBe(false)
+    expect(middleware.length).toBe(defaultMiddleware.length - 1)
+  })
+
+  it('removes the immutable middleware if disabled', () => {
+    const middleware = getDefaultMiddleware({ immutableCheck: false })
+    expect(middleware.length).toBe(defaultMiddleware.length - 1)
+  })
+
+  it('removes the serializable middleware if disabled', () => {
+    const middleware = getDefaultMiddleware({ serializableCheck: false })
+    expect(middleware.length).toBe(defaultMiddleware.length - 1)
+  })
+
+  it('removes the action creator middleware if disabled', () => {
+    const middleware = getDefaultMiddleware({ actionCreatorCheck: false })
+    expect(middleware.length).toBe(defaultMiddleware.length - 1)
+  })
+
+  it('allows passing options to thunk', () => {
+    const extraArgument = 42 as const
+
+    const m2 = getDefaultMiddleware({
+      thunk: false,
+    })
+
+    const dummyMiddleware: Middleware<
+      {
+        (action: Action<'actionListenerMiddleware/add'>): () => void
+      },
+      { counter: number }
+    > = (storeApi) => (next) => (action) => {
+      return next(action)
+    }
+
+    const dummyMiddleware2: Middleware<{}, { counter: number }> =
+      (storeApi) => (next) => (action) => {}
+
+    const testThunk: ThunkAction<
+      void,
+      { counter: number },
+      number,
+      UnknownAction
+    > = (dispatch, getState, extraArg) => {
+      expect(extraArg).toBe(extraArgument)
+    }
+
+    const reducer = () => ({ counter: 123 })
+
+    const store = configureStore({
+      reducer,
+      middleware: (gDM) => {
+        const middleware = gDM({
+          thunk: { extraArgument },
+          immutableCheck: false,
+          serializableCheck: false,
+          actionCreatorCheck: false,
+        })
+
+        const m3 = middleware.concat(dummyMiddleware, dummyMiddleware2)
+
+        return m3
+      },
+    })
+
+    store.dispatch(testThunk)
+  })
+
+  it('allows passing options to immutableCheck', () => {
+    let immutableCheckWasCalled = false
+
+    const middleware = () =>
+      getDefaultMiddleware({
+        thunk: false,
+        immutableCheck: {
+          isImmutable: () => {
+            immutableCheckWasCalled = true
+            return true
+          },
+        },
+        serializableCheck: false,
+        actionCreatorCheck: false,
+      })
+
+    const reducer = () => ({})
+
+    const store = configureStore({
+      reducer,
+      middleware,
+    })
+
+    expect(immutableCheckWasCalled).toBe(true)
+  })
+
+  it('allows passing options to serializableCheck', () => {
+    let serializableCheckWasCalled = false
+
+    const middleware = () =>
+      getDefaultMiddleware({
+        thunk: false,
+        immutableCheck: false,
+        serializableCheck: {
+          isSerializable: () => {
+            serializableCheckWasCalled = true
+            return true
+          },
+        },
+        actionCreatorCheck: false,
+      })
+
+    const reducer = () => ({})
+
+    const store = configureStore({
+      reducer,
+      middleware,
+    })
+
+    store.dispatch({ type: 'TEST_ACTION' })
+
+    expect(serializableCheckWasCalled).toBe(true)
+  })
+})
+
+it('allows passing options to actionCreatorCheck', () => {
+  let actionCreatorCheckWasCalled = false
+
+  const middleware = () =>
+    getDefaultMiddleware({
+      thunk: false,
+      immutableCheck: false,
+      serializableCheck: false,
+      actionCreatorCheck: {
+        isActionCreator: (action: unknown): action is Function => {
+          actionCreatorCheckWasCalled = true
+          return false
+        },
+      },
+    })
+
+  const reducer = () => ({})
+
+  const store = configureStore({
+    reducer,
+    middleware,
+  })
+
+  store.dispatch({ type: 'TEST_ACTION' })
+
+  expect(actionCreatorCheckWasCalled).toBe(true)
+})
+
+describe('Tuple functionality', () => {
+  const middleware1: Middleware = () => (next) => (action) => next(action)
+  const middleware2: Middleware = () => (next) => (action) => next(action)
+  const defaultMiddleware = getDefaultMiddleware()
+  const originalDefaultMiddleware = [...defaultMiddleware]
+
+  test('allows to prepend a single value', () => {
+    const prepended = defaultMiddleware.prepend(middleware1)
+
+    // value is prepended
+    expect(prepended).toEqual([middleware1, ...defaultMiddleware])
+    // returned value is of correct type
+    expect(prepended).toBeInstanceOf(Tuple)
+    // prepended is a new array
+    expect(prepended).not.toEqual(defaultMiddleware)
+    // defaultMiddleware is not modified
+    expect(defaultMiddleware).toEqual(originalDefaultMiddleware)
+  })
+
+  test('allows to prepend multiple values (array as first argument)', () => {
+    const prepended = defaultMiddleware.prepend([middleware1, middleware2])
+
+    // value is prepended
+    expect(prepended).toEqual([middleware1, middleware2, ...defaultMiddleware])
+    // returned value is of correct type
+    expect(prepended).toBeInstanceOf(Tuple)
+    // prepended is a new array
+    expect(prepended).not.toEqual(defaultMiddleware)
+    // defaultMiddleware is not modified
+    expect(defaultMiddleware).toEqual(originalDefaultMiddleware)
+  })
+
+  test('allows to prepend multiple values (rest)', () => {
+    const prepended = defaultMiddleware.prepend(middleware1, middleware2)
+
+    // value is prepended
+    expect(prepended).toEqual([middleware1, middleware2, ...defaultMiddleware])
+    // returned value is of correct type
+    expect(prepended).toBeInstanceOf(Tuple)
+    // prepended is a new array
+    expect(prepended).not.toEqual(defaultMiddleware)
+    // defaultMiddleware is not modified
+    expect(defaultMiddleware).toEqual(originalDefaultMiddleware)
+  })
+
+  test('allows to concat a single value', () => {
+    const concatenated = defaultMiddleware.concat(middleware1)
+
+    // value is concatenated
+    expect(concatenated).toEqual([...defaultMiddleware, middleware1])
+    // returned value is of correct type
+    expect(concatenated).toBeInstanceOf(Tuple)
+    // concatenated is a new array
+    expect(concatenated).not.toEqual(defaultMiddleware)
+    // defaultMiddleware is not modified
+    expect(defaultMiddleware).toEqual(originalDefaultMiddleware)
+  })
+
+  test('allows to concat multiple values (array as first argument)', () => {
+    const concatenated = defaultMiddleware.concat([middleware1, middleware2])
+
+    // value is concatenated
+    expect(concatenated).toEqual([
+      ...defaultMiddleware,
+      middleware1,
+      middleware2,
+    ])
+    // returned value is of correct type
+    expect(concatenated).toBeInstanceOf(Tuple)
+    // concatenated is a new array
+    expect(concatenated).not.toEqual(defaultMiddleware)
+    // defaultMiddleware is not modified
+    expect(defaultMiddleware).toEqual(originalDefaultMiddleware)
+  })
+
+  test('allows to concat multiple values (rest)', () => {
+    const concatenated = defaultMiddleware.concat(middleware1, middleware2)
+
+    // value is concatenated
+    expect(concatenated).toEqual([
+      ...defaultMiddleware,
+      middleware1,
+      middleware2,
+    ])
+    // returned value is of correct type
+    expect(concatenated).toBeInstanceOf(Tuple)
+    // concatenated is a new array
+    expect(concatenated).not.toEqual(defaultMiddleware)
+    // defaultMiddleware is not modified
+    expect(defaultMiddleware).toEqual(originalDefaultMiddleware)
+  })
+
+  test('allows to concat and then prepend', () => {
+    const concatenated = defaultMiddleware
+      .concat(middleware1)
+      .prepend(middleware2)
+
+    expect(concatenated).toEqual([
+      middleware2,
+      ...defaultMiddleware,
+      middleware1,
+    ])
+  })
+
+  test('allows to prepend and then concat', () => {
+    const concatenated = defaultMiddleware
+      .prepend(middleware2)
+      .concat(middleware1)
+
+    expect(concatenated).toEqual([
+      middleware2,
+      ...defaultMiddleware,
+      middleware1,
+    ])
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/immutableStateInvariantMiddleware.test.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/immutableStateInvariantMiddleware.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/immutableStateInvariantMiddleware.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,506 @@
+import { trackForMutations } from '@internal/immutableStateInvariantMiddleware'
+import { noop } from '@internal/listenerMiddleware/utils'
+import type {
+  ImmutableStateInvariantMiddlewareOptions,
+  Middleware,
+  MiddlewareAPI,
+  Store,
+} from '@reduxjs/toolkit'
+import {
+  createImmutableStateInvariantMiddleware,
+  isImmutableDefault,
+} from '@reduxjs/toolkit'
+
+type MWNext = Parameters<ReturnType<Middleware>>[0]
+
+describe('createImmutableStateInvariantMiddleware', () => {
+  let state: { foo: { bar: number[]; baz: string } }
+  const getState: Store['getState'] = () => state
+
+  function middleware(options: ImmutableStateInvariantMiddlewareOptions = {}) {
+    return createImmutableStateInvariantMiddleware(options)({
+      getState,
+    } as MiddlewareAPI)
+  }
+
+  beforeEach(() => {
+    state = { foo: { bar: [2, 3, 4], baz: 'baz' } }
+  })
+
+  it('sends the action through the middleware chain', () => {
+    const next: MWNext = vi.fn()
+    const dispatch = middleware()(next)
+    dispatch({ type: 'SOME_ACTION' })
+
+    expect(next).toHaveBeenCalledWith({
+      type: 'SOME_ACTION',
+    })
+  })
+
+  it('throws if mutating inside the dispatch', () => {
+    const next: MWNext = (action) => {
+      state.foo.bar.push(5)
+      return action
+    }
+
+    const dispatch = middleware()(next)
+
+    expect(() => {
+      dispatch({ type: 'SOME_ACTION' })
+    }).toThrow(new RegExp('foo\\.bar\\.3'))
+  })
+
+  it('throws if mutating between dispatches', () => {
+    const next: MWNext = (action) => action
+
+    const dispatch = middleware()(next)
+
+    dispatch({ type: 'SOME_ACTION' })
+    state.foo.bar.push(5)
+    expect(() => {
+      dispatch({ type: 'SOME_OTHER_ACTION' })
+    }).toThrow(new RegExp('foo\\.bar\\.3'))
+  })
+
+  it('does not throw if not mutating inside the dispatch', () => {
+    const next: MWNext = (action) => {
+      state = { ...state, foo: { ...state.foo, baz: 'changed!' } }
+      return action
+    }
+
+    const dispatch = middleware()(next)
+
+    expect(() => {
+      dispatch({ type: 'SOME_ACTION' })
+    }).not.toThrow()
+  })
+
+  it('does not throw if not mutating between dispatches', () => {
+    const next: MWNext = (action) => action
+
+    const dispatch = middleware()(next)
+
+    dispatch({ type: 'SOME_ACTION' })
+    state = { ...state, foo: { ...state.foo, baz: 'changed!' } }
+    expect(() => {
+      dispatch({ type: 'SOME_OTHER_ACTION' })
+    }).not.toThrow()
+  })
+
+  it('works correctly with circular references', () => {
+    const next: MWNext = (action) => action
+
+    const dispatch = middleware()(next)
+
+    let x: any = {}
+    let y: any = {}
+    x.y = y
+    y.x = x
+
+    expect(() => {
+      dispatch({ type: 'SOME_ACTION', x })
+    }).not.toThrow()
+  })
+
+  it('respects "isImmutable" option', function () {
+    const isImmutable = (value: any) => true
+    const next: MWNext = (action) => {
+      state.foo.bar.push(5)
+      return action
+    }
+
+    const dispatch = middleware({ isImmutable })(next)
+
+    expect(() => {
+      dispatch({ type: 'SOME_ACTION' })
+    }).not.toThrow()
+  })
+
+  it('respects "ignoredPaths" option', () => {
+    const next: MWNext = (action) => {
+      state.foo.bar.push(5)
+      return action
+    }
+
+    const dispatch1 = middleware({ ignoredPaths: ['foo.bar'] })(next)
+
+    expect(() => {
+      dispatch1({ type: 'SOME_ACTION' })
+    }).not.toThrow()
+
+    const dispatch2 = middleware({ ignoredPaths: [/^foo/] })(next)
+
+    expect(() => {
+      dispatch2({ type: 'SOME_ACTION' })
+    }).not.toThrow()
+  })
+
+  it('Should print a warning if execution takes too long', () => {
+    state.foo.bar = new Array(10000).fill({ value: 'more' })
+
+    const next: MWNext = (action) => action
+
+    const dispatch = middleware({ warnAfter: 4 })(next)
+
+    const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(noop)
+
+    try {
+      dispatch({ type: 'SOME_ACTION' })
+
+      expect(consoleWarnSpy).toHaveBeenCalledOnce()
+
+      expect(consoleWarnSpy).toHaveBeenLastCalledWith(
+        expect.stringMatching(
+          /^ImmutableStateInvariantMiddleware took \d*ms, which is more than the warning threshold of 4ms./,
+        ),
+      )
+    } finally {
+      consoleWarnSpy.mockRestore()
+    }
+  })
+
+  it('Should not print a warning if "next" takes too long', () => {
+    const next: MWNext = (action) => {
+      const started = Date.now()
+      while (Date.now() - started < 8) {}
+      return action
+    }
+
+    const dispatch = middleware({ warnAfter: 4 })(next)
+
+    const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(noop)
+
+    try {
+      dispatch({ type: 'SOME_ACTION' })
+
+      expect(consoleWarnSpy).not.toHaveBeenCalled()
+    } finally {
+      consoleWarnSpy.mockRestore()
+    }
+  })
+})
+
+describe('trackForMutations', () => {
+  function testCasesForMutation(spec: any) {
+    it('returns true and the mutated path', () => {
+      const state = spec.getState()
+      const options = spec.middlewareOptions || {}
+      const { isImmutable = isImmutableDefault, ignoredPaths } = options
+      const tracker = trackForMutations(isImmutable, ignoredPaths, state)
+      const newState = spec.fn(state)
+
+      expect(tracker.detectMutations()).toEqual({
+        wasMutated: true,
+        path: spec.path.join('.'),
+      })
+    })
+  }
+
+  function testCasesForNonMutation(spec: any) {
+    it('returns false', () => {
+      const state = spec.getState()
+      const options = spec.middlewareOptions || {}
+      const { isImmutable = isImmutableDefault, ignoredPaths } = options
+      const tracker = trackForMutations(isImmutable, ignoredPaths, state)
+      const newState = spec.fn(state)
+
+      expect(tracker.detectMutations()).toEqual({ wasMutated: false })
+    })
+  }
+
+  interface TestConfig {
+    getState: Store['getState']
+    fn: (s: any) => typeof s | object
+    middlewareOptions?: ImmutableStateInvariantMiddlewareOptions
+    path?: string[]
+  }
+
+  const mutations: Record<string, TestConfig> = {
+    'adding to nested array': {
+      getState: () => ({
+        foo: {
+          bar: [2, 3, 4],
+          baz: 'baz',
+        },
+        stuff: [],
+      }),
+      fn: (s) => {
+        s.foo.bar.push(5)
+        return s
+      },
+      path: ['foo', 'bar', '3'],
+    },
+    'adding to nested array and setting new root object': {
+      getState: () => ({
+        foo: {
+          bar: [2, 3, 4],
+          baz: 'baz',
+        },
+        stuff: [],
+      }),
+      fn: (s) => {
+        s.foo.bar.push(5)
+        return { ...s }
+      },
+      path: ['foo', 'bar', '3'],
+    },
+    'changing nested string': {
+      getState: () => ({
+        foo: {
+          bar: [2, 3, 4],
+          baz: 'baz',
+        },
+        stuff: [],
+      }),
+      fn: (s) => {
+        s.foo.baz = 'changed!'
+        return s
+      },
+      path: ['foo', 'baz'],
+    },
+    'removing nested state': {
+      getState: () => ({
+        foo: {
+          bar: [2, 3, 4],
+          baz: 'baz',
+        },
+        stuff: [],
+      }),
+      fn: (s) => {
+        delete s.foo
+        return s
+      },
+      path: ['foo'],
+    },
+    'adding to array': {
+      getState: () => ({
+        foo: {
+          bar: [2, 3, 4],
+          baz: 'baz',
+        },
+        stuff: [],
+      }),
+      fn: (s) => {
+        s.stuff.push(1)
+        return s
+      },
+      path: ['stuff', '0'],
+    },
+    'adding object to array': {
+      getState: () => ({
+        stuff: [],
+      }),
+      fn: (s) => {
+        s.stuff.push({ foo: 1, bar: 2 })
+        return s
+      },
+      path: ['stuff', '0'],
+    },
+    'mutating previous state and returning new state': {
+      getState: () => ({ counter: 0 }),
+      fn: (s) => {
+        s.mutation = true
+        return { ...s, counter: s.counter + 1 }
+      },
+      path: ['mutation'],
+    },
+    'mutating previous state with non immutable type and returning new state': {
+      getState: () => ({ counter: 0 }),
+      fn: (s) => {
+        s.mutation = [1, 2, 3]
+        return { ...s, counter: s.counter + 1 }
+      },
+      path: ['mutation'],
+    },
+    'mutating previous state with non immutable type and returning new state without that property':
+      {
+        getState: () => ({ counter: 0 }),
+        fn: (s) => {
+          s.mutation = [1, 2, 3]
+          return { counter: s.counter + 1 }
+        },
+        path: ['mutation'],
+      },
+    'mutating previous state with non immutable type and returning new simple state':
+      {
+        getState: () => ({ counter: 0 }),
+        fn: (s) => {
+          s.mutation = [1, 2, 3]
+          return 1
+        },
+        path: ['mutation'],
+      },
+    'mutating previous state by deleting property and returning new state without that property':
+      {
+        getState: () => ({ counter: 0, toBeDeleted: true }),
+        fn: (s) => {
+          delete s.toBeDeleted
+          return { counter: s.counter + 1 }
+        },
+        path: ['toBeDeleted'],
+      },
+    'mutating previous state by deleting nested property': {
+      getState: () => ({ nested: { counter: 0, toBeDeleted: true }, foo: 1 }),
+      fn: (s) => {
+        delete s.nested.toBeDeleted
+        return { nested: { counter: s.counter + 1 } }
+      },
+      path: ['nested', 'toBeDeleted'],
+    },
+    'update reference': {
+      getState: () => ({ foo: {} }),
+      fn: (s) => {
+        s.foo = {}
+        return s
+      },
+      path: ['foo'],
+    },
+    'cannot ignore root state': {
+      getState: () => ({ foo: {} }),
+      fn: (s) => {
+        s.foo = {}
+        return s
+      },
+      middlewareOptions: {
+        ignoredPaths: [''],
+      },
+      path: ['foo'],
+    },
+    'catching state mutation in non-ignored branch': {
+      getState: () => ({
+        foo: {
+          bar: [1, 2],
+        },
+        boo: {
+          yah: [1, 2],
+        },
+      }),
+      fn: (s) => {
+        s.foo.bar.push(3)
+        s.boo.yah.push(3)
+        return s
+      },
+      middlewareOptions: {
+        ignoredPaths: ['foo'],
+      },
+      path: ['boo', 'yah', '2'],
+    },
+  }
+
+  Object.keys(mutations).forEach((mutationDesc) => {
+    describe(mutationDesc, () => {
+      testCasesForMutation(mutations[mutationDesc])
+    })
+  })
+
+  const nonMutations: Record<string, TestConfig> = {
+    'not doing anything': {
+      getState: () => ({ a: 1, b: 2 }),
+      fn: (s) => s,
+    },
+    'from undefined to something': {
+      getState: () => undefined,
+      fn: (s) => ({ foo: 'bar' }),
+    },
+    'returning same state': {
+      getState: () => ({
+        foo: {
+          bar: [2, 3, 4],
+          baz: 'baz',
+        },
+        stuff: [],
+      }),
+      fn: (s) => s,
+    },
+    'returning a new state object with nested new string': {
+      getState: () => ({
+        foo: {
+          bar: [2, 3, 4],
+          baz: 'baz',
+        },
+        stuff: [],
+      }),
+      fn: (s) => {
+        return { ...s, foo: { ...s.foo, baz: 'changed!' } }
+      },
+    },
+    'returning a new state object with nested new array': {
+      getState: () => ({
+        foo: {
+          bar: [2, 3, 4],
+          baz: 'baz',
+        },
+        stuff: [],
+      }),
+      fn: (s) => {
+        return { ...s, foo: { ...s.foo, bar: [...s.foo.bar, 5] } }
+      },
+    },
+    'removing nested state': {
+      getState: () => ({
+        foo: {
+          bar: [2, 3, 4],
+          baz: 'baz',
+        },
+        stuff: [],
+      }),
+      fn: (s) => {
+        return { ...s, foo: {} }
+      },
+    },
+    'having a NaN in the state': {
+      getState: () => ({ a: NaN, b: Number.NaN }),
+      fn: (s) => s,
+    },
+    'ignoring branches from mutation detection': {
+      getState: () => ({
+        foo: {
+          bar: 'bar',
+        },
+      }),
+      fn: (s) => {
+        s.foo.bar = 'baz'
+        return s
+      },
+      middlewareOptions: {
+        ignoredPaths: ['foo'],
+      },
+    },
+    'ignoring nested branches from mutation detection': {
+      getState: () => ({
+        foo: {
+          bar: [1, 2],
+          boo: {
+            yah: [1, 2],
+          },
+        },
+      }),
+      fn: (s) => {
+        s.foo.bar.push(3)
+        s.foo.boo.yah.push(3)
+        return s
+      },
+      middlewareOptions: {
+        ignoredPaths: ['foo.bar', 'foo.boo.yah'],
+      },
+    },
+    'ignoring nested array indices from mutation detection': {
+      getState: () => ({
+        stuff: [{ a: 1 }, { a: 2 }],
+      }),
+      fn: (s) => {
+        s.stuff[1].a = 3
+        return s
+      },
+      middlewareOptions: {
+        ignoredPaths: ['stuff.1'],
+      },
+    },
+  }
+
+  Object.keys(nonMutations).forEach((nonMutationDesc) => {
+    describe(nonMutationDesc, () => {
+      testCasesForNonMutation(nonMutations[nonMutationDesc])
+    })
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/mapBuilders.test-d.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/mapBuilders.test-d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/mapBuilders.test-d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,416 @@
+import type { SerializedError } from '@internal/createAsyncThunk'
+import { createAsyncThunk } from '@internal/createAsyncThunk'
+import { executeReducerBuilderCallback } from '@internal/mapBuilders'
+import type { UnknownAction } from '@reduxjs/toolkit'
+import { createAction } from '@reduxjs/toolkit'
+
+describe('type tests', () => {
+  test('builder callback for actionMap', () => {
+    const increment = createAction<number, 'increment'>('increment')
+
+    const decrement = createAction<number, 'decrement'>('decrement')
+
+    executeReducerBuilderCallback<number>((builder) => {
+      builder.addCase(increment, (state, action) => {
+        expectTypeOf(state).toBeNumber()
+
+        expectTypeOf(action).toEqualTypeOf<{
+          type: 'increment'
+          payload: number
+        }>()
+
+        expectTypeOf(state).not.toBeString()
+
+        expectTypeOf(action).not.toMatchTypeOf<{
+          type: 'increment'
+          payload: string
+        }>()
+
+        expectTypeOf(action).not.toMatchTypeOf<{
+          type: 'decrement'
+          payload: number
+        }>()
+      })
+
+      builder.addCase('increment', (state, action) => {
+        expectTypeOf(state).toBeNumber()
+
+        expectTypeOf(action).toEqualTypeOf<{ type: 'increment' }>()
+
+        expectTypeOf(state).not.toBeString()
+
+        expectTypeOf(action).not.toMatchTypeOf<{ type: 'decrement' }>()
+
+        // this cannot be inferred and has to be manually specified
+        expectTypeOf(action).not.toMatchTypeOf<{
+          type: 'increment'
+          payload: number
+        }>()
+      })
+
+      builder.addCase(
+        increment,
+        (state, action: ReturnType<typeof increment>) => state,
+      )
+
+      // @ts-expect-error
+      builder.addCase(
+        increment,
+        (state, action: ReturnType<typeof decrement>) => state,
+      )
+
+      builder.addCase(
+        'increment',
+        (state, action: ReturnType<typeof increment>) => state,
+      )
+
+      // @ts-expect-error
+      builder.addCase(
+        'decrement',
+        (state, action: ReturnType<typeof increment>) => state,
+      )
+
+      // action type is inferred
+      builder.addMatcher(increment.match, (state, action) => {
+        expectTypeOf(action).toEqualTypeOf<ReturnType<typeof increment>>()
+      })
+
+      test('action type is inferred when type predicate lacks `type` property', () => {
+        type PredicateWithoutTypeProperty = {
+          payload: number
+        }
+
+        builder.addMatcher(
+          (action): action is PredicateWithoutTypeProperty => true,
+          (state, action) => {
+            expectTypeOf(action).toMatchTypeOf<PredicateWithoutTypeProperty>()
+
+            expectTypeOf(action).toMatchTypeOf<UnknownAction>()
+          },
+        )
+      })
+
+      // action type defaults to UnknownAction if no type predicate matcher is passed
+      builder.addMatcher(
+        () => true,
+        (state, action) => {
+          expectTypeOf(action).toMatchTypeOf<UnknownAction>()
+        },
+      )
+
+      // with a boolean checker, action can also be typed by type argument
+      builder.addMatcher<{ foo: boolean }>(
+        () => true,
+        (state, action) => {
+          expectTypeOf(action).toMatchTypeOf<{ foo: boolean }>()
+
+          expectTypeOf(action).toMatchTypeOf<UnknownAction>()
+        },
+      )
+
+      // addCase().addMatcher() is possible, action type inferred correctly
+      builder
+        .addCase(
+          'increment',
+          (state, action: ReturnType<typeof increment>) => state,
+        )
+        .addMatcher(decrement.match, (state, action) => {
+          expectTypeOf(action).toEqualTypeOf<ReturnType<typeof decrement>>()
+        })
+
+      // addCase().addDefaultCase() is possible, action type is UnknownAction
+      builder
+        .addCase(
+          'increment',
+          (state, action: ReturnType<typeof increment>) => state,
+        )
+        .addDefaultCase((state, action) => {
+          expectTypeOf(action).toMatchTypeOf<UnknownAction>()
+        })
+
+      test('addAsyncThunk() should prevent further calls to addCase() ', () => {
+        const asyncThunk = createAsyncThunk('test', () => {})
+        const b = builder.addAsyncThunk(asyncThunk, {
+          pending: () => {},
+          rejected: () => {},
+          fulfilled: () => {},
+          settled: () => {},
+        })
+
+        expectTypeOf(b).not.toHaveProperty('addCase')
+
+        expectTypeOf(b.addAsyncThunk).toBeFunction()
+
+        expectTypeOf(b.addMatcher).toBeCallableWith(increment.match, () => {})
+
+        expectTypeOf(b.addDefaultCase).toBeCallableWith(() => {})
+      })
+
+      test('addMatcher() should prevent further calls to addCase() and addAsyncThunk()', () => {
+        const b = builder.addMatcher(increment.match, () => {})
+
+        expectTypeOf(b).not.toHaveProperty('addCase')
+        expectTypeOf(b).not.toHaveProperty('addAsyncThunk')
+
+        expectTypeOf(b.addMatcher).toBeCallableWith(increment.match, () => {})
+
+        expectTypeOf(b.addDefaultCase).toBeCallableWith(() => {})
+      })
+
+      test('addDefaultCase() should prevent further calls to addCase(), addAsyncThunk(), addMatcher() and addDefaultCase', () => {
+        const b = builder.addDefaultCase(() => {})
+
+        expectTypeOf(b).not.toHaveProperty('addCase')
+
+        expectTypeOf(b).not.toHaveProperty('addAsyncThunk')
+
+        expectTypeOf(b).not.toHaveProperty('addMatcher')
+
+        expectTypeOf(b).not.toHaveProperty('addDefaultCase')
+      })
+
+      describe('`createAsyncThunk` actions work with `mapBuilder`', () => {
+        test('case 1: normal `createAsyncThunk`', () => {
+          const thunk = createAsyncThunk('test', () => {
+            return 'ret' as const
+          })
+          builder.addCase(thunk.pending, (_, action) => {
+            expectTypeOf(action).toMatchTypeOf<{
+              payload: undefined
+              meta: {
+                arg: void
+                requestId: string
+                requestStatus: 'pending'
+              }
+            }>()
+          })
+
+          builder.addCase(thunk.rejected, (_, action) => {
+            expectTypeOf(action).toMatchTypeOf<{
+              payload: unknown
+              error: SerializedError
+              meta: {
+                arg: void
+                requestId: string
+                requestStatus: 'rejected'
+                aborted: boolean
+                condition: boolean
+                rejectedWithValue: boolean
+              }
+            }>()
+          })
+          builder.addCase(thunk.fulfilled, (_, action) => {
+            expectTypeOf(action).toMatchTypeOf<{
+              payload: 'ret'
+              meta: {
+                arg: void
+                requestId: string
+                requestStatus: 'fulfilled'
+              }
+            }>()
+          })
+
+          builder.addAsyncThunk(thunk, {
+            pending(_, action) {
+              expectTypeOf(action).toMatchTypeOf<{
+                payload: undefined
+                meta: {
+                  arg: void
+                  requestId: string
+                  requestStatus: 'pending'
+                }
+              }>()
+            },
+            rejected(_, action) {
+              expectTypeOf(action).toMatchTypeOf<{
+                payload: unknown
+                error: SerializedError
+                meta: {
+                  arg: void
+                  requestId: string
+                  requestStatus: 'rejected'
+                  aborted: boolean
+                  condition: boolean
+                  rejectedWithValue: boolean
+                }
+              }>()
+            },
+            fulfilled(_, action) {
+              expectTypeOf(action).toMatchTypeOf<{
+                payload: 'ret'
+                meta: {
+                  arg: void
+                  requestId: string
+                  requestStatus: 'fulfilled'
+                }
+              }>()
+            },
+            settled(_, action) {
+              expectTypeOf(action).toMatchTypeOf<
+                | {
+                    payload: 'ret'
+                    meta: {
+                      arg: void
+                      requestId: string
+                      requestStatus: 'fulfilled'
+                    }
+                  }
+                | {
+                    payload: unknown
+                    error: SerializedError
+                    meta: {
+                      arg: void
+                      requestId: string
+                      requestStatus: 'rejected'
+                      aborted: boolean
+                      condition: boolean
+                      rejectedWithValue: boolean
+                    }
+                  }
+              >()
+            },
+          })
+        })
+
+        test('case 2: `createAsyncThunk` with `meta`', () => {
+          const thunk = createAsyncThunk<
+            'ret',
+            void,
+            {
+              pendingMeta: { startedTimeStamp: number }
+              fulfilledMeta: {
+                fulfilledTimeStamp: number
+                baseQueryMeta: 'meta!'
+              }
+              rejectedMeta: {
+                baseQueryMeta: 'meta!'
+              }
+            }
+          >(
+            'test',
+            (_, api) => {
+              return api.fulfillWithValue('ret' as const, {
+                fulfilledTimeStamp: 5,
+                baseQueryMeta: 'meta!',
+              })
+            },
+            {
+              getPendingMeta() {
+                return { startedTimeStamp: 0 }
+              },
+            },
+          )
+
+          builder.addCase(thunk.pending, (_, action) => {
+            expectTypeOf(action).toMatchTypeOf<{
+              payload: undefined
+              meta: {
+                arg: void
+                requestId: string
+                requestStatus: 'pending'
+                startedTimeStamp: number
+              }
+            }>()
+          })
+
+          builder.addCase(thunk.rejected, (_, action) => {
+            expectTypeOf(action).toMatchTypeOf<{
+              payload: unknown
+              error: SerializedError
+              meta: {
+                arg: void
+                requestId: string
+                requestStatus: 'rejected'
+                aborted: boolean
+                condition: boolean
+                rejectedWithValue: boolean
+                baseQueryMeta?: 'meta!'
+              }
+            }>()
+
+            if (action.meta.rejectedWithValue) {
+              expectTypeOf(action.meta.baseQueryMeta).toEqualTypeOf<'meta!'>()
+            }
+          })
+          builder.addCase(thunk.fulfilled, (_, action) => {
+            expectTypeOf(action).toMatchTypeOf<{
+              payload: 'ret'
+              meta: {
+                arg: void
+                requestId: string
+                requestStatus: 'fulfilled'
+                baseQueryMeta: 'meta!'
+              }
+            }>()
+          })
+
+          builder.addAsyncThunk(thunk, {
+            pending(_, action) {
+              expectTypeOf(action).toMatchTypeOf<{
+                payload: undefined
+                meta: {
+                  arg: void
+                  requestId: string
+                  requestStatus: 'pending'
+                  startedTimeStamp: number
+                }
+              }>()
+            },
+            rejected(_, action) {
+              expectTypeOf(action).toMatchTypeOf<{
+                payload: unknown
+                error: SerializedError
+                meta: {
+                  arg: void
+                  requestId: string
+                  requestStatus: 'rejected'
+                  aborted: boolean
+                  condition: boolean
+                  rejectedWithValue: boolean
+                  baseQueryMeta?: 'meta!'
+                }
+              }>()
+            },
+            fulfilled(_, action) {
+              expectTypeOf(action).toMatchTypeOf<{
+                payload: 'ret'
+                meta: {
+                  arg: void
+                  requestId: string
+                  requestStatus: 'fulfilled'
+                  baseQueryMeta: 'meta!'
+                }
+              }>()
+            },
+            settled(_, action) {
+              expectTypeOf(action).toMatchTypeOf<
+                | {
+                    payload: 'ret'
+                    meta: {
+                      arg: void
+                      requestId: string
+                      requestStatus: 'fulfilled'
+                      baseQueryMeta: 'meta!'
+                    }
+                  }
+                | {
+                    payload: unknown
+                    error: SerializedError
+                    meta: {
+                      arg: void
+                      requestId: string
+                      requestStatus: 'rejected'
+                      aborted: boolean
+                      condition: boolean
+                      rejectedWithValue: boolean
+                      baseQueryMeta?: 'meta!'
+                    }
+                  }
+              >()
+            },
+          })
+        })
+      })
+    })
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/matchers.test-d.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/matchers.test-d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/matchers.test-d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,296 @@
+import type { UnknownAction } from 'redux'
+import type { SerializedError } from '../../src'
+import {
+  createAction,
+  createAsyncThunk,
+  isAllOf,
+  isAnyOf,
+  isAsyncThunkAction,
+  isFulfilled,
+  isPending,
+  isRejected,
+  isRejectedWithValue,
+} from '../../src'
+
+const action: UnknownAction = { type: 'foo' }
+
+describe('type tests', () => {
+  describe('isAnyOf', () => {
+    test('isAnyOf correctly narrows types when used with action creators', () => {
+      const actionA = createAction('a', () => {
+        return {
+          payload: {
+            prop1: 1,
+            prop3: 2,
+          },
+        }
+      })
+
+      const actionB = createAction('b', () => {
+        return {
+          payload: {
+            prop1: 1,
+            prop2: 2,
+          },
+        }
+      })
+
+      if (isAnyOf(actionA, actionB)(action)) {
+        expectTypeOf(action.payload).toHaveProperty('prop1')
+
+        expectTypeOf(action.payload).not.toHaveProperty('prop2')
+
+        expectTypeOf(action.payload).not.toHaveProperty('prop3')
+      }
+    })
+
+    test('isAnyOf correctly narrows types when used with async thunks', () => {
+      const asyncThunk1 = createAsyncThunk<{ prop1: number; prop3: number }>(
+        'asyncThunk1',
+
+        async () => {
+          return {
+            prop1: 1,
+            prop3: 3,
+          }
+        },
+      )
+
+      const asyncThunk2 = createAsyncThunk<{ prop1: number; prop2: number }>(
+        'asyncThunk2',
+
+        async () => {
+          return {
+            prop1: 1,
+            prop2: 2,
+          }
+        },
+      )
+
+      if (isAnyOf(asyncThunk1.fulfilled, asyncThunk2.fulfilled)(action)) {
+        expectTypeOf(action.payload).toHaveProperty('prop1')
+
+        expectTypeOf(action.payload).not.toHaveProperty('prop2')
+
+        expectTypeOf(action.payload).not.toHaveProperty('prop3')
+      }
+    })
+
+    test('isAnyOf correctly narrows types when used with type guards', () => {
+      interface ActionA {
+        type: 'a'
+        payload: {
+          prop1: 1
+          prop3: 2
+        }
+      }
+
+      interface ActionB {
+        type: 'b'
+        payload: {
+          prop1: 1
+          prop2: 2
+        }
+      }
+
+      const guardA = (v: any): v is ActionA => {
+        return v.type === 'a'
+      }
+
+      const guardB = (v: any): v is ActionB => {
+        return v.type === 'b'
+      }
+
+      if (isAnyOf(guardA, guardB)(action)) {
+        expectTypeOf(action.payload).toHaveProperty('prop1')
+
+        expectTypeOf(action.payload).not.toHaveProperty('prop2')
+
+        expectTypeOf(action.payload).not.toHaveProperty('prop3')
+      }
+    })
+  })
+
+  describe('isAllOf', () => {
+    interface SpecialAction {
+      payload: {
+        special: boolean
+      }
+    }
+
+    const isSpecialAction = (v: any): v is SpecialAction => {
+      return v.meta.isSpecial
+    }
+
+    test('isAllOf correctly narrows types when used with action creators and type guards', () => {
+      const actionA = createAction('a', () => {
+        return {
+          payload: {
+            prop1: 1,
+            prop3: 2,
+          },
+        }
+      })
+
+      if (isAllOf(actionA, isSpecialAction)(action)) {
+        expectTypeOf(action.payload).toHaveProperty('prop1')
+
+        expectTypeOf(action.payload).not.toHaveProperty('prop2')
+
+        expectTypeOf(action.payload).toHaveProperty('prop3')
+
+        expectTypeOf(action.payload).toHaveProperty('special')
+      }
+    })
+
+    test('isAllOf correctly narrows types when used with async thunks and type guards', () => {
+      const asyncThunk1 = createAsyncThunk<{ prop1: number; prop3: number }>(
+        'asyncThunk1',
+
+        async () => {
+          return {
+            prop1: 1,
+            prop3: 3,
+          }
+        },
+      )
+
+      if (isAllOf(asyncThunk1.fulfilled, isSpecialAction)(action)) {
+        expectTypeOf(action.payload).toHaveProperty('prop1')
+
+        expectTypeOf(action.payload).not.toHaveProperty('prop2')
+
+        expectTypeOf(action.payload).toHaveProperty('prop3')
+
+        expectTypeOf(action.payload).toHaveProperty('special')
+      }
+    })
+
+    test('isAnyOf correctly narrows types when used with type guards', () => {
+      interface ActionA {
+        type: 'a'
+        payload: {
+          prop1: 1
+          prop3: 2
+        }
+      }
+
+      const guardA = (v: any): v is ActionA => {
+        return v.type === 'a'
+      }
+
+      if (isAllOf(guardA, isSpecialAction)(action)) {
+        expectTypeOf(action.payload).toHaveProperty('prop1')
+
+        expectTypeOf(action.payload).not.toHaveProperty('prop2')
+
+        expectTypeOf(action.payload).toHaveProperty('prop3')
+
+        expectTypeOf(action.payload).toHaveProperty('special')
+      }
+    })
+
+    test('isPending correctly narrows types', () => {
+      if (isPending(action)) {
+        expectTypeOf(action.payload).toBeUndefined()
+
+        expectTypeOf(action).not.toHaveProperty('error')
+      }
+
+      const thunk = createAsyncThunk<string>('a', () => 'result')
+
+      if (isPending(thunk)(action)) {
+        expectTypeOf(action.payload).toBeUndefined()
+
+        expectTypeOf(action).not.toHaveProperty('error')
+      }
+    })
+
+    test('isRejected correctly narrows types', () => {
+      if (isRejected(action)) {
+        // might be there if rejected with payload
+        expectTypeOf(action.payload).toBeUnknown()
+
+        expectTypeOf(action.error).toEqualTypeOf<SerializedError>()
+      }
+
+      const thunk = createAsyncThunk<string>('a', () => 'result')
+
+      if (isRejected(thunk)(action)) {
+        // might be there if rejected with payload
+        expectTypeOf(action.payload).toBeUnknown()
+
+        expectTypeOf(action.error).toEqualTypeOf<SerializedError>()
+      }
+    })
+
+    test('isFulfilled correctly narrows types', () => {
+      if (isFulfilled(action)) {
+        expectTypeOf(action.payload).toBeUnknown()
+
+        expectTypeOf(action).not.toHaveProperty('error')
+      }
+
+      const thunk = createAsyncThunk<string>('a', () => 'result')
+      if (isFulfilled(thunk)(action)) {
+        expectTypeOf(action.payload).toBeString()
+
+        expectTypeOf(action).not.toHaveProperty('error')
+      }
+    })
+
+    test('isAsyncThunkAction correctly narrows types', () => {
+      if (isAsyncThunkAction(action)) {
+        expectTypeOf(action.payload).toBeUnknown()
+
+        // do not expect an error property because pending/fulfilled lack it
+        expectTypeOf(action).not.toHaveProperty('error')
+      }
+
+      const thunk = createAsyncThunk<string>('a', () => 'result')
+      if (isAsyncThunkAction(thunk)(action)) {
+        // we should expect the payload to be available, but of unknown type because the action may be pending/rejected
+        expectTypeOf(action.payload).toBeUnknown()
+
+        // do not expect an error property because pending/fulfilled lack it
+        expectTypeOf(action).not.toHaveProperty('error')
+      }
+    })
+
+    test('isRejectedWithValue correctly narrows types', () => {
+      if (isRejectedWithValue(action)) {
+        expectTypeOf(action.payload).toBeUnknown()
+
+        expectTypeOf(action.error).toEqualTypeOf<SerializedError>()
+      }
+
+      const thunk = createAsyncThunk<
+        string,
+        void,
+        { rejectValue: { message: string } }
+      >('a', () => 'result')
+      if (isRejectedWithValue(thunk)(action)) {
+        expectTypeOf(action.payload).toEqualTypeOf({ message: '' as string })
+
+        expectTypeOf(action.error).toEqualTypeOf<SerializedError>()
+      }
+    })
+  })
+
+  test('matchersAcceptSpreadArguments', () => {
+    const thunk1 = createAsyncThunk('a', () => 'a')
+    const thunk2 = createAsyncThunk('b', () => 'b')
+    const interestingThunks = [thunk1, thunk2]
+    const interestingPendingThunks = interestingThunks.map(
+      (thunk) => thunk.pending,
+    )
+    const interestingFulfilledThunks = interestingThunks.map(
+      (thunk) => thunk.fulfilled,
+    )
+
+    const isLoading = isAnyOf(...interestingPendingThunks)
+    const isNotLoading = isAnyOf(...interestingFulfilledThunks)
+
+    const isAllLoading = isAllOf(...interestingPendingThunks)
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/matchers.test.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/matchers.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/matchers.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,461 @@
+import { vi } from 'vitest'
+import type { ThunkAction, UnknownAction } from '@reduxjs/toolkit'
+import {
+  isAllOf,
+  isAnyOf,
+  isAsyncThunkAction,
+  isFulfilled,
+  isPending,
+  isRejected,
+  isRejectedWithValue,
+  createAction,
+  createAsyncThunk,
+  createReducer,
+} from '@reduxjs/toolkit'
+
+const thunk: ThunkAction<any, any, any, UnknownAction> = () => {}
+
+describe('isAnyOf', () => {
+  it('returns true only if any matchers match (match function)', () => {
+    const actionA = createAction<string>('a')
+    const actionB = createAction<number>('b')
+
+    const trueAction = {
+      type: 'a',
+      payload: 'payload',
+    }
+
+    expect(isAnyOf(actionA, actionB)(trueAction)).toEqual(true)
+
+    const falseAction = {
+      type: 'c',
+      payload: 'payload',
+    }
+
+    expect(isAnyOf(actionA, actionB)(falseAction)).toEqual(false)
+  })
+
+  it('returns true only if any type guards match', () => {
+    const actionA = createAction<string>('a')
+    const actionB = createAction<number>('b')
+
+    const isActionA = actionA.match
+    const isActionB = actionB.match
+
+    const trueAction = {
+      type: 'a',
+      payload: 'payload',
+    }
+
+    expect(isAnyOf(isActionA, isActionB)(trueAction)).toEqual(true)
+
+    const falseAction = {
+      type: 'c',
+      payload: 'payload',
+    }
+
+    expect(isAnyOf(isActionA, isActionB)(falseAction)).toEqual(false)
+  })
+
+  it('returns true only if any matchers match (thunk action creators)', () => {
+    const thunkA = createAsyncThunk<string>('a', () => {
+      return 'noop'
+    })
+    const thunkB = createAsyncThunk<number>('b', () => {
+      return 0
+    })
+
+    const action = thunkA.fulfilled('fakeRequestId', 'test')
+
+    expect(isAnyOf(thunkA.fulfilled, thunkB.fulfilled)(action)).toEqual(true)
+
+    expect(
+      isAnyOf(thunkA.pending, thunkA.rejected, thunkB.fulfilled)(action),
+    ).toEqual(false)
+  })
+
+  it('works with reducers', () => {
+    const actionA = createAction<string>('a')
+    const actionB = createAction<number>('b')
+
+    const trueAction = {
+      type: 'a',
+      payload: 'payload',
+    }
+
+    const initialState = { value: false }
+
+    const reducer = createReducer(initialState, (builder) => {
+      builder.addMatcher(isAnyOf(actionA, actionB), (state) => {
+        return { ...state, value: true }
+      })
+    })
+
+    expect(reducer(initialState, trueAction)).toEqual({ value: true })
+
+    const falseAction = {
+      type: 'c',
+      payload: 'payload',
+    }
+
+    expect(reducer(initialState, falseAction)).toEqual(initialState)
+  })
+})
+
+describe('isAllOf', () => {
+  it('returns true only if all matchers match', () => {
+    const actionA = createAction<string>('a')
+
+    interface SpecialAction {
+      payload: 'SPECIAL'
+    }
+
+    const isActionSpecial = (action: any): action is SpecialAction => {
+      return action.payload === 'SPECIAL'
+    }
+
+    const trueAction = {
+      type: 'a',
+      payload: 'SPECIAL',
+    }
+
+    expect(isAllOf(actionA, isActionSpecial)(trueAction)).toEqual(true)
+
+    const falseAction = {
+      type: 'a',
+      payload: 'ORDINARY',
+    }
+
+    expect(isAllOf(actionA, isActionSpecial)(falseAction)).toEqual(false)
+
+    const thunkA = createAsyncThunk<string>('a', () => 'result')
+
+    const specialThunkAction = thunkA.fulfilled('SPECIAL', 'fakeRequestId')
+
+    expect(isAllOf(thunkA.fulfilled, isActionSpecial)(specialThunkAction)).toBe(
+      true,
+    )
+
+    const ordinaryThunkAction = thunkA.fulfilled('ORDINARY', 'fakeRequestId')
+
+    expect(
+      isAllOf(thunkA.fulfilled, isActionSpecial)(ordinaryThunkAction),
+    ).toBe(false)
+  })
+})
+
+describe('isPending', () => {
+  test('should return false for a regular action', () => {
+    const action = createAction<string>('action/type')('testPayload')
+
+    expect(isPending()(action)).toBe(false)
+    expect(isPending(action)).toBe(false)
+    expect(isPending(thunk)).toBe(false)
+  })
+
+  test('should return true only for pending async thunk actions', () => {
+    const thunk = createAsyncThunk<string>('a', () => 'result')
+
+    const pendingAction = thunk.pending('fakeRequestId')
+    expect(isPending()(pendingAction)).toBe(true)
+    expect(isPending(pendingAction)).toBe(true)
+
+    const rejectedAction = thunk.rejected(
+      new Error('rejected'),
+      'fakeRequestId',
+    )
+    expect(isPending()(rejectedAction)).toBe(false)
+
+    const fulfilledAction = thunk.fulfilled('result', 'fakeRequestId')
+    expect(isPending()(fulfilledAction)).toBe(false)
+  })
+
+  test('should return true only for thunks provided as arguments', () => {
+    const thunkA = createAsyncThunk<string>('a', () => 'result')
+    const thunkB = createAsyncThunk<string>('b', () => 'result')
+    const thunkC = createAsyncThunk<string>('c', () => 'result')
+
+    const matchAC = isPending(thunkA, thunkC)
+    const matchB = isPending(thunkB)
+
+    function testPendingAction(
+      thunk: typeof thunkA | typeof thunkB | typeof thunkC,
+      expected: boolean,
+    ) {
+      const pendingAction = thunk.pending('fakeRequestId')
+      expect(matchAC(pendingAction)).toBe(expected)
+      expect(matchB(pendingAction)).toBe(!expected)
+
+      const rejectedAction = thunk.rejected(
+        new Error('rejected'),
+        'fakeRequestId',
+      )
+      expect(matchAC(rejectedAction)).toBe(false)
+
+      const fulfilledAction = thunk.fulfilled('result', 'fakeRequestId')
+      expect(matchAC(fulfilledAction)).toBe(false)
+    }
+
+    testPendingAction(thunkA, true)
+    testPendingAction(thunkC, true)
+    testPendingAction(thunkB, false)
+  })
+})
+
+describe('isRejected', () => {
+  test('should return false for a regular action', () => {
+    const action = createAction<string>('action/type')('testPayload')
+
+    expect(isRejected()(action)).toBe(false)
+    expect(isRejected(action)).toBe(false)
+    expect(isRejected(thunk)).toBe(false)
+  })
+
+  test('should return true only for rejected async thunk actions', () => {
+    const thunk = createAsyncThunk<string>('a', () => 'result')
+
+    const pendingAction = thunk.pending('fakeRequestId')
+    expect(isRejected()(pendingAction)).toBe(false)
+
+    const rejectedAction = thunk.rejected(
+      new Error('rejected'),
+      'fakeRequestId',
+    )
+    expect(isRejected()(rejectedAction)).toBe(true)
+    expect(isRejected(rejectedAction)).toBe(true)
+
+    const fulfilledAction = thunk.fulfilled('result', 'fakeRequestId')
+    expect(isRejected()(fulfilledAction)).toBe(false)
+  })
+
+  test('should return true only for thunks provided as arguments', () => {
+    const thunkA = createAsyncThunk<string>('a', () => 'result')
+    const thunkB = createAsyncThunk<string>('b', () => 'result')
+    const thunkC = createAsyncThunk<string>('c', () => 'result')
+
+    const matchAC = isRejected(thunkA, thunkC)
+    const matchB = isRejected(thunkB)
+
+    function testRejectedAction(
+      thunk: typeof thunkA | typeof thunkB | typeof thunkC,
+      expected: boolean,
+    ) {
+      const pendingAction = thunk.pending('fakeRequestId')
+      expect(matchAC(pendingAction)).toBe(false)
+
+      const rejectedAction = thunk.rejected(
+        new Error('rejected'),
+        'fakeRequestId',
+      )
+      expect(matchAC(rejectedAction)).toBe(expected)
+      expect(matchB(rejectedAction)).toBe(!expected)
+
+      const fulfilledAction = thunk.fulfilled('result', 'fakeRequestId')
+      expect(matchAC(fulfilledAction)).toBe(false)
+    }
+
+    testRejectedAction(thunkA, true)
+    testRejectedAction(thunkC, true)
+    testRejectedAction(thunkB, false)
+  })
+})
+
+describe('isRejectedWithValue', () => {
+  test('should return false for a regular action', () => {
+    const action = createAction<string>('action/type')('testPayload')
+
+    expect(isRejectedWithValue()(action)).toBe(false)
+    expect(isRejectedWithValue(action)).toBe(false)
+    expect(isRejectedWithValue(thunk)).toBe(false)
+  })
+
+  test('should return true only for rejected-with-value async thunk actions', async () => {
+    const thunk = createAsyncThunk<string>('a', (_, { rejectWithValue }) => {
+      return rejectWithValue('rejectWithValue!')
+    })
+
+    const pendingAction = thunk.pending('fakeRequestId')
+    expect(isRejectedWithValue()(pendingAction)).toBe(false)
+
+    const rejectedAction = thunk.rejected(
+      new Error('rejected'),
+      'fakeRequestId',
+    )
+    expect(isRejectedWithValue()(rejectedAction)).toBe(false)
+
+    const getState = vi.fn(() => ({}))
+    const dispatch = vi.fn((x: any) => x)
+    const extra = {}
+
+    // note: doesn't throw because we don't unwrap it
+    const rejectedWithValueAction = await thunk()(dispatch, getState, extra)
+
+    expect(isRejectedWithValue()(rejectedWithValueAction)).toBe(true)
+
+    const fulfilledAction = thunk.fulfilled('result', 'fakeRequestId')
+    expect(isRejectedWithValue()(fulfilledAction)).toBe(false)
+  })
+
+  test('should return true only for thunks provided as arguments', async () => {
+    const payloadCreator = (_: any, { rejectWithValue }: any) => {
+      return rejectWithValue('rejectWithValue!')
+    }
+
+    const thunkA = createAsyncThunk<string>('a', payloadCreator)
+    const thunkB = createAsyncThunk<string>('b', payloadCreator)
+    const thunkC = createAsyncThunk<string>('c', payloadCreator)
+
+    const matchAC = isRejectedWithValue(thunkA, thunkC)
+    const matchB = isRejectedWithValue(thunkB)
+
+    async function testRejectedAction(
+      thunk: typeof thunkA | typeof thunkB | typeof thunkC,
+      expected: boolean,
+    ) {
+      const pendingAction = thunk.pending('fakeRequestId')
+      expect(matchAC(pendingAction)).toBe(false)
+
+      const rejectedAction = thunk.rejected(
+        new Error('rejected'),
+        'fakeRequestId',
+      )
+      // rejected-with-value is a narrower requirement than rejected
+      expect(matchAC(rejectedAction)).toBe(false)
+
+      const getState = vi.fn(() => ({}))
+      const dispatch = vi.fn((x: any) => x)
+      const extra = {}
+
+      // note: doesn't throw because we don't unwrap it
+      const rejectedWithValueAction = await thunk()(dispatch, getState, extra)
+
+      expect(matchAC(rejectedWithValueAction)).toBe(expected)
+      expect(matchB(rejectedWithValueAction)).toBe(!expected)
+
+      const fulfilledAction = thunk.fulfilled('result', 'fakeRequestId')
+      expect(matchAC(fulfilledAction)).toBe(false)
+    }
+
+    await testRejectedAction(thunkA, true)
+    await testRejectedAction(thunkC, true)
+    await testRejectedAction(thunkB, false)
+  })
+})
+
+describe('isFulfilled', () => {
+  test('should return false for a regular action', () => {
+    const action = createAction<string>('action/type')('testPayload')
+
+    expect(isFulfilled()(action)).toBe(false)
+    expect(isFulfilled(action)).toBe(false)
+    expect(isFulfilled(thunk)).toBe(false)
+  })
+
+  test('should return true only for fulfilled async thunk actions', () => {
+    const thunk = createAsyncThunk<string>('a', () => 'result')
+
+    const pendingAction = thunk.pending('fakeRequestId')
+    expect(isFulfilled()(pendingAction)).toBe(false)
+
+    const rejectedAction = thunk.rejected(
+      new Error('rejected'),
+      'fakeRequestId',
+    )
+    expect(isFulfilled()(rejectedAction)).toBe(false)
+
+    const fulfilledAction = thunk.fulfilled('result', 'fakeRequestId')
+    expect(isFulfilled()(fulfilledAction)).toBe(true)
+    expect(isFulfilled(fulfilledAction)).toBe(true)
+  })
+
+  test('should return true only for thunks provided as arguments', () => {
+    const thunkA = createAsyncThunk<string>('a', () => 'result')
+    const thunkB = createAsyncThunk<string>('b', () => 'result')
+    const thunkC = createAsyncThunk<string>('c', () => 'result')
+
+    const matchAC = isFulfilled(thunkA, thunkC)
+    const matchB = isFulfilled(thunkB)
+
+    function testFulfilledAction(
+      thunk: typeof thunkA | typeof thunkB | typeof thunkC,
+      expected: boolean,
+    ) {
+      const pendingAction = thunk.pending('fakeRequestId')
+      expect(matchAC(pendingAction)).toBe(false)
+
+      const rejectedAction = thunk.rejected(
+        new Error('rejected'),
+        'fakeRequestId',
+      )
+      expect(matchAC(rejectedAction)).toBe(false)
+
+      const fulfilledAction = thunk.fulfilled('result', 'fakeRequestId')
+      expect(matchAC(fulfilledAction)).toBe(expected)
+      expect(matchB(fulfilledAction)).toBe(!expected)
+    }
+
+    testFulfilledAction(thunkA, true)
+    testFulfilledAction(thunkC, true)
+    testFulfilledAction(thunkB, false)
+  })
+})
+
+describe('isAsyncThunkAction', () => {
+  test('should return false for a regular action', () => {
+    const action = createAction<string>('action/type')('testPayload')
+
+    expect(isAsyncThunkAction()(action)).toBe(false)
+    expect(isAsyncThunkAction(action)).toBe(false)
+    expect(isAsyncThunkAction(thunk)).toBe(false)
+  })
+
+  test('should return true for any async thunk action if no arguments were provided', () => {
+    const thunk = createAsyncThunk<string>('a', () => 'result')
+    const matcher = isAsyncThunkAction()
+
+    const pendingAction = thunk.pending('fakeRequestId')
+    expect(matcher(pendingAction)).toBe(true)
+
+    const rejectedAction = thunk.rejected(
+      new Error('rejected'),
+      'fakeRequestId',
+    )
+    expect(matcher(rejectedAction)).toBe(true)
+
+    const fulfilledAction = thunk.fulfilled('result', 'fakeRequestId')
+    expect(matcher(fulfilledAction)).toBe(true)
+  })
+
+  test('should return true only for thunks provided as arguments', () => {
+    const thunkA = createAsyncThunk<string>('a', () => 'result')
+    const thunkB = createAsyncThunk<string>('b', () => 'result')
+    const thunkC = createAsyncThunk<string>('c', () => 'result')
+
+    const matchAC = isAsyncThunkAction(thunkA, thunkC)
+    const matchB = isAsyncThunkAction(thunkB)
+
+    function testAllActions(
+      thunk: typeof thunkA | typeof thunkB | typeof thunkC,
+      expected: boolean,
+    ) {
+      const pendingAction = thunk.pending('fakeRequestId')
+      expect(matchAC(pendingAction)).toBe(expected)
+      expect(matchB(pendingAction)).toBe(!expected)
+
+      const rejectedAction = thunk.rejected(
+        new Error('rejected'),
+        'fakeRequestId',
+      )
+      expect(matchAC(rejectedAction)).toBe(expected)
+      expect(matchB(rejectedAction)).toBe(!expected)
+
+      const fulfilledAction = thunk.fulfilled('result', 'fakeRequestId')
+      expect(matchAC(fulfilledAction)).toBe(expected)
+      expect(matchB(fulfilledAction)).toBe(!expected)
+    }
+
+    testAllActions(thunkA, true)
+    testAllActions(thunkC, true)
+    testAllActions(thunkB, false)
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/serializableStateInvariantMiddleware.test.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/serializableStateInvariantMiddleware.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/serializableStateInvariantMiddleware.test.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,663 @@
+import { noop } from '@internal/listenerMiddleware/utils'
+import { isNestedFrozen } from '@internal/serializableStateInvariantMiddleware'
+import type { Reducer } from '@reduxjs/toolkit'
+import {
+  configureStore,
+  createNextState,
+  createSerializableStateInvariantMiddleware,
+  findNonSerializableValue,
+  isPlain,
+  Tuple,
+} from '@reduxjs/toolkit'
+
+// Mocking console
+const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(noop)
+
+const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(noop)
+
+afterEach(() => {
+  vi.clearAllMocks()
+})
+
+afterAll(() => {
+  vi.restoreAllMocks()
+})
+
+describe('findNonSerializableValue', () => {
+  it('Should return false if no matching values are found', () => {
+    const obj = {
+      a: 42,
+      b: {
+        b1: 'test',
+      },
+      c: [99, { d: 123 }],
+    }
+
+    const result = findNonSerializableValue(obj)
+
+    expect(result).toBe(false)
+  })
+
+  it('Should return a keypath and the value if it finds a non-serializable value', () => {
+    function testFunction() {}
+
+    const obj = {
+      a: 42,
+      b: {
+        b1: testFunction,
+      },
+      c: [99, { d: 123 }],
+    }
+
+    const result = findNonSerializableValue(obj)
+
+    expect(result).toEqual({ keyPath: 'b.b1', value: testFunction })
+  })
+
+  it('Should return the first non-serializable value it finds', () => {
+    const map = new Map()
+    const symbol = Symbol.for('testSymbol')
+
+    const obj = {
+      a: 42,
+      b: {
+        b1: 1,
+      },
+      c: [99, { d: 123 }, map, symbol, 'test'],
+      d: symbol,
+    }
+
+    const result = findNonSerializableValue(obj)
+
+    expect(result).toEqual({ keyPath: 'c.2', value: map })
+  })
+
+  it('Should return a specific value if the root object is non-serializable', () => {
+    const value = new Map()
+    const result = findNonSerializableValue(value)
+
+    expect(result).toEqual({ keyPath: '<root>', value })
+  })
+
+  it('Should accept null as a valid value', () => {
+    const obj = {
+      a: 42,
+      b: {
+        b1: 1,
+      },
+      c: null,
+    }
+
+    const result = findNonSerializableValue(obj)
+
+    expect(result).toEqual(false)
+  })
+})
+
+describe('serializableStateInvariantMiddleware', () => {
+  it('Should log an error when a non-serializable action is dispatched', () => {
+    const reducer: Reducer = (state = 0, _action) => state + 1
+
+    const serializableStateInvariantMiddleware =
+      createSerializableStateInvariantMiddleware()
+
+    const store = configureStore({
+      reducer,
+      middleware: () => new Tuple(serializableStateInvariantMiddleware),
+    })
+
+    const symbol = Symbol.for('SOME_CONSTANT')
+    const dispatchedAction = { type: 'an-action', payload: symbol }
+
+    store.dispatch(dispatchedAction)
+
+    expect(consoleErrorSpy).toHaveBeenCalledOnce()
+
+    expect(consoleErrorSpy).toHaveBeenLastCalledWith(
+      `A non-serializable value was detected in an action, in the path: \`payload\`. Value:`,
+      symbol,
+      `\nTake a look at the logic that dispatched this action: `,
+      dispatchedAction,
+      `\n(See https://redux.js.org/faq/actions#why-should-type-be-a-string-or-at-least-serializable-why-should-my-action-types-be-constants)`,
+      `\n(To allow non-serializable values see: https://redux-toolkit.js.org/usage/usage-guide#working-with-non-serializable-data)`,
+    )
+  })
+
+  it('Should log an error when a non-serializable value is in state', () => {
+    const ACTION_TYPE = 'TEST_ACTION'
+
+    const initialState = {
+      a: 0,
+    }
+
+    const badValue = new Map()
+
+    const reducer: Reducer = (state = initialState, action) => {
+      switch (action.type) {
+        case ACTION_TYPE: {
+          return {
+            a: badValue,
+          }
+        }
+        default:
+          return state
+      }
+    }
+
+    const serializableStateInvariantMiddleware =
+      createSerializableStateInvariantMiddleware()
+
+    const store = configureStore({
+      reducer: {
+        testSlice: reducer,
+      },
+      middleware: () => new Tuple(serializableStateInvariantMiddleware),
+    })
+
+    store.dispatch({ type: ACTION_TYPE })
+
+    expect(consoleErrorSpy).toHaveBeenCalledOnce()
+
+    expect(consoleErrorSpy).toHaveBeenLastCalledWith(
+      `A non-serializable value was detected in the state, in the path: \`testSlice.a\`. Value:`,
+      badValue,
+      `\nTake a look at the reducer(s) handling this action type: TEST_ACTION.
+(See https://redux.js.org/faq/organizing-state#can-i-put-functions-promises-or-other-non-serializable-items-in-my-store-state)`,
+    )
+  })
+
+  describe('consumer tolerated structures', () => {
+    const nonSerializableValue = new Map()
+
+    const nestedSerializableObjectWithBadValue = {
+      isSerializable: true,
+      entries: (): [string, any][] => [
+        ['good-string', 'Good!'],
+        ['good-number', 1337],
+        ['bad-map-instance', nonSerializableValue],
+      ],
+    }
+
+    const serializableObject = {
+      isSerializable: true,
+      entries: (): [string, any][] => [
+        ['first', 1],
+        ['second', 'B!'],
+        ['third', nestedSerializableObjectWithBadValue],
+      ],
+    }
+
+    it('Should log an error when a non-serializable value is nested in state', () => {
+      const ACTION_TYPE = 'TEST_ACTION'
+
+      const initialState = {
+        a: 0,
+      }
+
+      const reducer: Reducer = (state = initialState, action) => {
+        switch (action.type) {
+          case ACTION_TYPE: {
+            return {
+              a: serializableObject,
+            }
+          }
+          default:
+            return state
+        }
+      }
+
+      // use default options
+      const serializableStateInvariantMiddleware =
+        createSerializableStateInvariantMiddleware()
+
+      const store = configureStore({
+        reducer: {
+          testSlice: reducer,
+        },
+        middleware: () => new Tuple(serializableStateInvariantMiddleware),
+      })
+
+      store.dispatch({ type: ACTION_TYPE })
+
+      expect(consoleErrorSpy).toHaveBeenCalledOnce()
+
+      // since default options are used, the `entries` function in `serializableObject` will cause the error
+      expect(consoleErrorSpy).toHaveBeenLastCalledWith(
+        `A non-serializable value was detected in the state, in the path: \`testSlice.a.entries\`. Value:`,
+        serializableObject.entries,
+        `\nTake a look at the reducer(s) handling this action type: TEST_ACTION.
+(See https://redux.js.org/faq/organizing-state#can-i-put-functions-promises-or-other-non-serializable-items-in-my-store-state)`,
+      )
+    })
+
+    it('Should use consumer supplied isSerializable and getEntries options to tolerate certain structures', () => {
+      const ACTION_TYPE = 'TEST_ACTION'
+
+      const initialState = {
+        a: 0,
+      }
+
+      const isSerializable = (val: any): boolean =>
+        val.isSerializable || isPlain(val)
+      const getEntries = (val: any): [string, any][] =>
+        val.isSerializable ? val.entries() : Object.entries(val)
+
+      const reducer: Reducer = (state = initialState, action) => {
+        switch (action.type) {
+          case ACTION_TYPE: {
+            return {
+              a: serializableObject,
+            }
+          }
+          default:
+            return state
+        }
+      }
+
+      const serializableStateInvariantMiddleware =
+        createSerializableStateInvariantMiddleware({
+          isSerializable,
+          getEntries,
+        })
+
+      const store = configureStore({
+        reducer: {
+          testSlice: reducer,
+        },
+        middleware: () => new Tuple(serializableStateInvariantMiddleware),
+      })
+
+      store.dispatch({ type: ACTION_TYPE })
+
+      expect(consoleErrorSpy).toHaveBeenCalledOnce()
+
+      // error reported is from a nested class instance, rather than the `entries` function `serializableObject`
+      expect(consoleErrorSpy).toHaveBeenLastCalledWith(
+        `A non-serializable value was detected in the state, in the path: \`testSlice.a.third.bad-map-instance\`. Value:`,
+        nonSerializableValue,
+        `\nTake a look at the reducer(s) handling this action type: TEST_ACTION.
+(See https://redux.js.org/faq/organizing-state#can-i-put-functions-promises-or-other-non-serializable-items-in-my-store-state)`,
+      )
+    })
+  })
+
+  it('Should use the supplied isSerializable function to determine serializability', () => {
+    const ACTION_TYPE = 'TEST_ACTION'
+
+    const initialState = {
+      a: 0,
+    }
+
+    const badValue = new Map()
+
+    const reducer: Reducer = (state = initialState, action) => {
+      switch (action.type) {
+        case ACTION_TYPE: {
+          return {
+            a: badValue,
+          }
+        }
+        default:
+          return state
+      }
+    }
+
+    const serializableStateInvariantMiddleware =
+      createSerializableStateInvariantMiddleware({
+        isSerializable: () => true,
+      })
+
+    const store = configureStore({
+      reducer: {
+        testSlice: reducer,
+      },
+      middleware: () => new Tuple(serializableStateInvariantMiddleware),
+    })
+
+    store.dispatch({ type: ACTION_TYPE })
+
+    // Supplied 'isSerializable' considers all values serializable, hence
+    // no error logging is expected:
+    expect(consoleErrorSpy).not.toHaveBeenCalled()
+  })
+
+  it('should not check serializability for ignored action types', () => {
+    let numTimesCalled = 0
+
+    const serializableStateMiddleware =
+      createSerializableStateInvariantMiddleware({
+        isSerializable: () => {
+          numTimesCalled++
+          return true
+        },
+        ignoredActions: ['IGNORE_ME'],
+      })
+
+    const store = configureStore({
+      reducer: () => ({}),
+      middleware: () => new Tuple(serializableStateMiddleware),
+    })
+
+    expect(numTimesCalled).toBe(0)
+
+    store.dispatch({ type: 'IGNORE_ME' })
+
+    // The state check only calls `isSerializable` once
+    expect(numTimesCalled).toBe(1)
+
+    store.dispatch({ type: 'ANY_OTHER_ACTION' })
+
+    // Action checks call `isSerializable` 2+ times when enabled
+    expect(numTimesCalled).toBeGreaterThanOrEqual(3)
+  })
+
+  describe('ignored action paths', () => {
+    function reducer() {
+      return 0
+    }
+    const nonSerializableValue = new Map()
+
+    it('default value: meta.arg', () => {
+      configureStore({
+        reducer,
+        middleware: () =>
+          new Tuple(createSerializableStateInvariantMiddleware()),
+      }).dispatch({ type: 'test', meta: { arg: nonSerializableValue } })
+
+      expect(consoleErrorSpy).not.toHaveBeenCalled()
+    })
+
+    it('default value can be overridden', () => {
+      configureStore({
+        reducer,
+        middleware: () =>
+          new Tuple(
+            createSerializableStateInvariantMiddleware({
+              ignoredActionPaths: [],
+            }),
+          ),
+      }).dispatch({ type: 'test', meta: { arg: nonSerializableValue } })
+
+      expect(consoleErrorSpy).toHaveBeenCalledOnce()
+
+      expect(consoleErrorSpy).toHaveBeenLastCalledWith(
+        `A non-serializable value was detected in an action, in the path: \`meta.arg\`. Value:`,
+        nonSerializableValue,
+        `\nTake a look at the logic that dispatched this action: `,
+        { type: 'test', meta: { arg: nonSerializableValue } },
+        `\n(See https://redux.js.org/faq/actions#why-should-type-be-a-string-or-at-least-serializable-why-should-my-action-types-be-constants)`,
+        `\n(To allow non-serializable values see: https://redux-toolkit.js.org/usage/usage-guide#working-with-non-serializable-data)`,
+      )
+    })
+
+    it('can specify (multiple) different values', () => {
+      configureStore({
+        reducer,
+        middleware: () =>
+          new Tuple(
+            createSerializableStateInvariantMiddleware({
+              ignoredActionPaths: ['payload', 'meta.arg'],
+            }),
+          ),
+      }).dispatch({
+        type: 'test',
+        payload: { arg: nonSerializableValue },
+        meta: { arg: nonSerializableValue },
+      })
+
+      expect(consoleErrorSpy).not.toHaveBeenCalled()
+    })
+
+    it('can specify regexp', () => {
+      configureStore({
+        reducer,
+        middleware: () =>
+          new Tuple(
+            createSerializableStateInvariantMiddleware({
+              ignoredActionPaths: [/^payload\..*$/],
+            }),
+          ),
+      }).dispatch({
+        type: 'test',
+        payload: { arg: nonSerializableValue },
+      })
+
+      expect(consoleErrorSpy).not.toHaveBeenCalled()
+    })
+  })
+
+  it('allows ignoring actions entirely', () => {
+    let numTimesCalled = 0
+
+    const serializableStateMiddleware =
+      createSerializableStateInvariantMiddleware({
+        isSerializable: () => {
+          numTimesCalled++
+          return true
+        },
+        ignoreActions: true,
+      })
+
+    const store = configureStore({
+      reducer: () => ({}),
+      middleware: () => new Tuple(serializableStateMiddleware),
+    })
+
+    expect(numTimesCalled).toBe(0)
+
+    store.dispatch({ type: 'THIS_DOESNT_MATTER' })
+
+    // `isSerializable` is called once for a state check
+    expect(numTimesCalled).toBe(1)
+
+    store.dispatch({ type: 'THIS_DOESNT_MATTER_AGAIN' })
+
+    expect(numTimesCalled).toBe(2)
+  })
+
+  it('should not check serializability for ignored slice names', () => {
+    const ACTION_TYPE = 'TEST_ACTION'
+
+    const initialState = {
+      a: 0,
+    }
+
+    const badValue = new Map()
+
+    const reducer: Reducer = (state = initialState, action) => {
+      switch (action.type) {
+        case ACTION_TYPE: {
+          return {
+            a: badValue,
+            b: {
+              c: badValue,
+              d: badValue,
+            },
+            e: { f: badValue },
+            g: {
+              h: badValue,
+              i: badValue,
+            },
+          }
+        }
+        default:
+          return state
+      }
+    }
+
+    const serializableStateInvariantMiddleware =
+      createSerializableStateInvariantMiddleware({
+        ignoredPaths: [
+          // Test for ignoring a single value
+          'testSlice.a',
+          // Test for ignoring a single nested value
+          'testSlice.b.c',
+          // Test for ignoring an object and its children
+          'testSlice.e',
+          // Test for ignoring based on RegExp
+          /^testSlice\.g\..*$/,
+        ],
+      })
+
+    const store = configureStore({
+      reducer: {
+        testSlice: reducer,
+      },
+      middleware: () => new Tuple(serializableStateInvariantMiddleware),
+    })
+
+    store.dispatch({ type: ACTION_TYPE })
+
+    expect(consoleErrorSpy).toHaveBeenCalledOnce()
+
+    // testSlice.b.d was not covered in ignoredPaths, so will still log the error
+    expect(consoleErrorSpy).toHaveBeenLastCalledWith(
+      `A non-serializable value was detected in the state, in the path: \`testSlice.b.d\`. Value:`,
+      badValue,
+      `\nTake a look at the reducer(s) handling this action type: TEST_ACTION.
+(See https://redux.js.org/faq/organizing-state#can-i-put-functions-promises-or-other-non-serializable-items-in-my-store-state)`,
+    )
+  })
+
+  it('allows ignoring state entirely', () => {
+    const badValue = new Map()
+    let numTimesCalled = 0
+    const reducer = () => badValue
+    const store = configureStore({
+      reducer,
+      middleware: () =>
+        new Tuple(
+          createSerializableStateInvariantMiddleware({
+            isSerializable: () => {
+              numTimesCalled++
+              return true
+            },
+            ignoreState: true,
+          }),
+        ),
+    })
+
+    expect(numTimesCalled).toBe(0)
+
+    store.dispatch({ type: 'test' })
+
+    expect(consoleErrorSpy).not.toHaveBeenCalled()
+
+    // Should be called twice for the action - there is an initial check for early returns, then a second and potentially 3rd for nested properties
+    expect(numTimesCalled).toBe(2)
+  })
+
+  it('never calls isSerializable if both ignoreState and ignoreActions are true', () => {
+    const badValue = new Map()
+    let numTimesCalled = 0
+    const reducer = () => badValue
+    const store = configureStore({
+      reducer,
+      middleware: () =>
+        new Tuple(
+          createSerializableStateInvariantMiddleware({
+            isSerializable: () => {
+              numTimesCalled++
+              return true
+            },
+            ignoreState: true,
+            ignoreActions: true,
+          }),
+        ),
+    })
+
+    expect(numTimesCalled).toBe(0)
+
+    store.dispatch({ type: 'TEST', payload: new Date() })
+    store.dispatch({ type: 'OTHER_THING' })
+
+    expect(numTimesCalled).toBe(0)
+  })
+
+  it('Should print a warning if execution takes too long', () => {
+    const reducer: Reducer = (state = 42, action) => {
+      return state
+    }
+
+    const serializableStateInvariantMiddleware =
+      createSerializableStateInvariantMiddleware({ warnAfter: 4 })
+
+    const store = configureStore({
+      reducer: {
+        testSlice: reducer,
+      },
+      middleware: () => new Tuple(serializableStateInvariantMiddleware),
+    })
+
+    store.dispatch({
+      type: 'SOME_ACTION',
+      payload: new Array(10_000).fill({ value: 'more' }),
+    })
+
+    expect(consoleWarnSpy).toHaveBeenCalledOnce()
+
+    expect(consoleWarnSpy).toHaveBeenLastCalledWith(
+      expect.stringMatching(
+        /^SerializableStateInvariantMiddleware took \d*ms, which is more than the warning threshold of 4ms./,
+      ),
+    )
+  })
+
+  it('Should not print a warning if "reducer" takes too long', () => {
+    const reducer: Reducer = (state = 42, action) => {
+      const started = Date.now()
+      while (Date.now() - started < 8) {}
+      return state
+    }
+
+    const serializableStateInvariantMiddleware =
+      createSerializableStateInvariantMiddleware({ warnAfter: 4 })
+
+    const store = configureStore({
+      reducer: {
+        testSlice: reducer,
+      },
+      middleware: () => new Tuple(serializableStateInvariantMiddleware),
+    })
+
+    store.dispatch({ type: 'SOME_ACTION' })
+
+    expect(consoleErrorSpy).not.toHaveBeenCalled()
+  })
+
+  it('Should cache its results', () => {
+    let numPlainChecks = 0
+    const countPlainChecks = (x: any) => {
+      numPlainChecks++
+      return isPlain(x)
+    }
+
+    const serializableStateInvariantMiddleware =
+      createSerializableStateInvariantMiddleware({
+        isSerializable: countPlainChecks,
+      })
+
+    const store = configureStore({
+      reducer: (state = [], action) => {
+        if (action.type === 'SET_STATE') return action.payload
+        return state
+      },
+      middleware: () => new Tuple(serializableStateInvariantMiddleware),
+    })
+
+    const state = createNextState([], () =>
+      new Array(50).fill(0).map((x, i) => ({ i })),
+    )
+    expect(isNestedFrozen(state)).toBe(true)
+
+    store.dispatch({
+      type: 'SET_STATE',
+      payload: state,
+    })
+    expect(numPlainChecks).toBeGreaterThan(state.length)
+
+    numPlainChecks = 0
+    store.dispatch({ type: 'NOOP' })
+    expect(numPlainChecks).toBeLessThan(10)
+  })
+})
Index: node_modules/@reduxjs/toolkit/src/tests/utils/CustomMatchers.d.ts
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/utils/CustomMatchers.d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/utils/CustomMatchers.d.ts	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,16 @@
+import type { Assertion, AsymmetricMatchersContaining } from 'vitest'
+
+interface CustomMatchers<R = unknown> {
+  toMatchSequence(...matchers: Array<(arg: any) => boolean>): R
+}
+
+declare module 'vitest' {
+  interface Assertion<T = any> extends CustomMatchers<T> {}
+  interface AsymmetricMatchersContaining extends CustomMatchers {}
+}
+
+declare global {
+  namespace jest {
+    interface Matchers<R> extends CustomMatchers<R> {}
+  }
+}
Index: node_modules/@reduxjs/toolkit/src/tests/utils/helpers.tsx
===================================================================
--- node_modules/@reduxjs/toolkit/src/tests/utils/helpers.tsx	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
+++ node_modules/@reduxjs/toolkit/src/tests/utils/helpers.tsx	(revision a762898ecd37a452c782821d4c2c4955c6ed2521)
@@ -0,0 +1,217 @@
+import type {
+  EnhancedStore,
+  Middleware,
+  Reducer,
+  Store,
+  UnknownAction,
+} from '@reduxjs/toolkit'
+import { configureStore } from '@reduxjs/toolkit'
+import { setupListeners } from '@reduxjs/toolkit/query'
+import { useCallback, useEffect, useRef } from 'react'
+
+import { Provider } from 'react-redux'
+
+import { act, cleanup } from '@testing-library/react'
+
+export const ANY = 0 as any
+
+export const DEFAULT_DELAY_MS = 150
+
+export const getSerializedHeaders = (headers: Headers = new Headers()) => {
+  const result: Record<string, string> = {}
+  headers.forEach((val, key) => {
+    result[key] = val
+  })
+  return result
+}
+
+export async function waitMs(time = DEFAULT_DELAY_MS) {
+  const now = Date.now()
+  while (Date.now() < now + time) {
+    await new Promise((res) => process.nextTick(res))
+  }
+}
+
+export function waitForFakeTimer(time = DEFAULT_DELAY_MS) {
+  return new Promise((resolve) => setTimeout(resolve, time))
+}
+
+export function withProvider(store: Store<any>) {
+  return function Wrapper({ children }: any) {
+    return <Provider store={store}>{children}</Provider>
+  }
+}
+
+export const hookWaitFor = async (cb: () => void, time = 2000) => {
+  const startedAt = Date.now()
+
+  while (true) {
+    try {
+      cb()
+      return true
+    } catch (e) {
+      if (Date.now() > startedAt + time) {
+        throw e
+      }
+      await act(async () => {
+        await waitMs(2)
+      })
+    }
+  }
+}
+export const fakeTimerWaitFor = async (cb: () => void, time = 2000) => {
+  const startedAt = Date.now()
+
+  while (true) {
+    try {
+      cb()
+      return true
+    } catch (e) {
+      if (Date.now() > startedAt + time) {
+        throw e
+      }
+      await act(async () => {
+        await vi.advanceTimersByTimeAsync(2)
+      })
+    }
+  }
+}
+
+export const useRenderCounter = () => {
+  const countRef = useRef(0)
+
+  useEffect(() => {
+    countRef.current += 1
+  })
+
+  useEffect(() => {
+    return () => {
+      countRef.current = 0
+    }
+  }, [])
+
+  return useCallback(() => countRef.current, [])
+}
+
+expect.extend({
+  toMatchSequence(
+    _actions: UnknownAction[],
+    ...matchers: Array<(arg: any) => boolean>
+  ) {
+    const actions = _actions.concat()
+    actions.shift() // remove INIT
+
+    for (let i = 0; i < matchers.length; i++) {
+      if (!matchers[i](actions[i])) {
+        return {
+          message: () =>
+            `Action ${actions[i].type} does not match sequence at position ${i}.
+All actions:
+${actions.map((a) => a.type).join('\n')}`,
+          pass: false,
+        }
+      }
+    }
+    return {
+      message: () => `All actions match the sequence.`,
+      pass: true,
+    }
+  },
+})
+
+export const actionsReducer = {
+  actions: (state: UnknownAction[] = [], action: UnknownAction) => {
+    // As of 2.0-beta.4, we are going to ignore all `subscriptionsUpdated` actions in tests
+    if (action.type.includes('subscriptionsUpdated')) {
+      return state
+    }
+
+    return [...state, action]
+  },
+}
+
+export function setupApiStore<
+  A extends {
+    reducerPath: 'api'
+    reducer: Reducer<any, any>
+    middleware: Middleware
+    util: { resetApiState(): any }
+  },
+  R extends Record<string, Reducer<any, any>> = Record<never, never>,
+>(
+  api: A,
+  extraReducers?: R,
+  options: {
+    withoutListeners?: boolean
+    withoutTestLifecycles?: boolean
+    middleware?: {
+      prepend?: Middleware[]
+      concat?: Middleware[]
+    }
+  } = {},
+) {
+  const { middleware } = options
+  const getStore = () =>
+    configureStore({
+      reducer: { api: api.reducer, ...extraReducers },
+      middleware: (gdm) => {
+        const tempMiddleware = gdm({
+          serializableCheck: false,
+          immutableCheck: false,
+        }).concat(api.middleware)
+
+        return tempMiddleware
+          .concat(middleware?.concat ?? [])
+          .prepend(middleware?.prepend ?? []) as typeof tempMiddleware
+      },
+      enhancers: (gde) =>
+        gde({
+          autoBatch: false,
+        }),
+    })
+
+  type State = {
+    api: ReturnType<A['reducer']>
+  } & {
+    [K in keyof R]: ReturnType<R[K]>
+  }
+  type StoreType = EnhancedStore<
+    {
+      api: ReturnType<A['reducer']>
+    } & {
+      [K in keyof R]: ReturnType<R[K]>
+    },
+    UnknownAction,
+    ReturnType<typeof getStore> extends EnhancedStore<any, any, infer M>
+      ? M
+      : never
+  >
+
+  const initialStore = getStore() as StoreType
+  const refObj = {
+    api,
+    store: initialStore,
+    wrapper: withProvider(initialStore),
+  }
+  let cleanupListeners: () => void
+
+  if (!options.withoutTestLifecycles) {
+    beforeEach(() => {
+      const store = getStore() as StoreType
+      refObj.store = store
+      refObj.wrapper = withProvider(store)
+      if (!options.withoutListeners) {
+        cleanupListeners = setupListeners(store.dispatch)
+      }
+    })
+    afterEach(() => {
+      cleanup()
+      if (!options.withoutListeners) {
+        cleanupListeners()
+      }
+      refObj.store.dispatch(api.util.resetApiState())
+    })
+  }
+
+  return refObj
+}
