From e1256f3789b97c932ab2200d9de05d410db023fa Mon Sep 17 00:00:00 2001 From: Anton Dalgren Date: Wed, 17 Jul 2024 12:52:37 +0200 Subject: [PATCH] feat: Adds ExtraArgument to withTypes for listenerMiddleware. These changes are based upon the changes in introduction of withTypes for the listenerMiddleware. --- docs/api/createListenerMiddleware.mdx | 5 +- .../listenerMiddleware.withTypes.test-d.ts | 23 +++-- .../listenerMiddleware.withTypes.test.ts | 12 ++- .../toolkit/src/listenerMiddleware/types.ts | 84 ++++++++++++------- 4 files changed, 81 insertions(+), 43 deletions(-) diff --git a/docs/api/createListenerMiddleware.mdx b/docs/api/createListenerMiddleware.mdx index 050fbd20b9..a805e2ebe9 100644 --- a/docs/api/createListenerMiddleware.mdx +++ b/docs/api/createListenerMiddleware.mdx @@ -488,11 +488,14 @@ To fix this, the middleware provides types for defining "pre-typed" versions of import { createListenerMiddleware, addListener } from '@reduxjs/toolkit' import type { RootState, AppDispatch } from './store' +declare type ExtraArgument = {foo: string}; + export const listenerMiddleware = createListenerMiddleware() export const startAppListening = listenerMiddleware.startListening.withTypes< RootState, - AppDispatch + AppDispatch, + ExtraArgument >() export const addAppListener = addListener.withTypes() diff --git a/packages/toolkit/src/listenerMiddleware/tests/listenerMiddleware.withTypes.test-d.ts b/packages/toolkit/src/listenerMiddleware/tests/listenerMiddleware.withTypes.test-d.ts index 6756144579..ae6fd6c46d 100644 --- a/packages/toolkit/src/listenerMiddleware/tests/listenerMiddleware.withTypes.test-d.ts +++ b/packages/toolkit/src/listenerMiddleware/tests/listenerMiddleware.withTypes.test-d.ts @@ -64,6 +64,7 @@ type AppThunk = ThunkAction< unknown, Action > +type ExtraArgument = { foo: string } describe('listenerMiddleware.withTypes()', () => { const listenerMiddleware = createListenerMiddleware() @@ -77,11 +78,12 @@ describe('listenerMiddleware.withTypes()', () => { test('startListening.withTypes', () => { const startAppListening = listenerMiddleware.startListening.withTypes< RootState, - AppDispatch + AppDispatch, + ExtraArgument >() expectTypeOf(startAppListening).toEqualTypeOf< - TypedStartListening + TypedStartListening >() startAppListening({ @@ -102,6 +104,8 @@ describe('listenerMiddleware.withTypes()', () => { expectTypeOf(stateCurrent).toEqualTypeOf() + expectTypeOf(listenerApi.extra).toEqualTypeOf() + timeout = 1 takeResult = await listenerApi.take(increment.match, timeout) @@ -111,10 +115,10 @@ describe('listenerMiddleware.withTypes()', () => { }) test('addListener.withTypes', () => { - const addAppListener = addListener.withTypes() + const addAppListener = addListener.withTypes() expectTypeOf(addAppListener).toEqualTypeOf< - TypedAddListener + TypedAddListener >() store.dispatch( @@ -126,27 +130,30 @@ describe('listenerMiddleware.withTypes()', () => { expectTypeOf(state).toEqualTypeOf() expectTypeOf(listenerApi.dispatch).toEqualTypeOf() + + expectTypeOf(listenerApi.extra).toEqualTypeOf() }, }), ) }) test('removeListener.withTypes', () => { - const removeAppListener = removeListener.withTypes() + const removeAppListener = removeListener.withTypes() expectTypeOf(removeAppListener).toEqualTypeOf< - TypedRemoveListener + TypedRemoveListener >() }) test('stopListening.withTypes', () => { const stopAppListening = listenerMiddleware.stopListening.withTypes< RootState, - AppDispatch + AppDispatch, + ExtraArgument >() expectTypeOf(stopAppListening).toEqualTypeOf< - TypedStopListening + TypedStopListening >() }) }) diff --git a/packages/toolkit/src/listenerMiddleware/tests/listenerMiddleware.withTypes.test.ts b/packages/toolkit/src/listenerMiddleware/tests/listenerMiddleware.withTypes.test.ts index 84bcf1ff2c..8d9da271f8 100644 --- a/packages/toolkit/src/listenerMiddleware/tests/listenerMiddleware.withTypes.test.ts +++ b/packages/toolkit/src/listenerMiddleware/tests/listenerMiddleware.withTypes.test.ts @@ -55,21 +55,25 @@ type AppThunk = ThunkAction< Action > +type ExtraArgument = { foo: string } + const listenerMiddleware = createListenerMiddleware() const startAppListening = listenerMiddleware.startListening.withTypes< RootState, - AppDispatch + AppDispatch, + ExtraArgument >() const stopAppListening = listenerMiddleware.stopListening.withTypes< RootState, - AppDispatch + AppDispatch, + ExtraArgument >() -const addAppListener = addListener.withTypes() +const addAppListener = addListener.withTypes() -const removeAppListener = removeListener.withTypes() +const removeAppListener = removeListener.withTypes() describe('startAppListening.withTypes', () => { test('should return startListening', () => { diff --git a/packages/toolkit/src/listenerMiddleware/types.ts b/packages/toolkit/src/listenerMiddleware/types.ts index 73a7ef1c0e..95a1749254 100644 --- a/packages/toolkit/src/listenerMiddleware/types.ts +++ b/packages/toolkit/src/listenerMiddleware/types.ts @@ -511,11 +511,12 @@ export type RemoveListenerOverloads< unknown, UnknownAction >, + ExtraArgument = unknown, > = AddListenerOverloads< boolean, StateType, DispatchType, - any, + ExtraArgument, UnsubscribeListenerOptions > @@ -556,22 +557,23 @@ export type TypedAddListener< > & { /** * Creates a "pre-typed" version of `addListener` - * where the `state` and `dispatch` types are predefined. + * where the `state`, `dispatch` and `extra` types are predefined. * - * This allows you to set the `state` and `dispatch` types once, + * This allows you to set the `state`, `dispatch` and `extra` types once, * eliminating the need to specify them with every `addListener` call. * - * @returns A pre-typed `addListener` with the state and dispatch types already defined. + * @returns A pre-typed `addListener` with the state, dispatch and extra types already defined. * * @example * ```ts * import { addListener } from '@reduxjs/toolkit' * - * export const addAppListener = addListener.withTypes() + * export const addAppListener = addListener.withTypes() * ``` * * @template OverrideStateType - The specific type of state the middleware listener operates on. * @template OverrideDispatchType - The specific type of the dispatch function. + * @template OverrideExtraArgument - The specific type of the extra object. * * @since 2.1.0 */ @@ -581,8 +583,9 @@ export type TypedAddListener< OverrideStateType, unknown, UnknownAction - >, - >() => TypedAddListener + >, + OverrideExtraArgument = unknown, + >() => TypedAddListener } /** @@ -597,6 +600,7 @@ export type TypedRemoveListener< unknown, UnknownAction >, + ExtraArgument = unknown, Payload = ListenerEntry, T extends string = 'listenerMiddleware/remove', > = BaseActionCreator & @@ -604,27 +608,33 @@ export type TypedRemoveListener< PayloadAction, StateType, DispatchType, - any, + ExtraArgument, UnsubscribeListenerOptions > & { /** * Creates a "pre-typed" version of `removeListener` - * where the `state` and `dispatch` types are predefined. + * where the `state`, `dispatch` and `extra` types are predefined. * - * This allows you to set the `state` and `dispatch` types once, + * This allows you to set the `state`, `dispatch` and `extra` types once, * eliminating the need to specify them with every `removeListener` call. * - * @returns A pre-typed `removeListener` with the state and dispatch types already defined. + * @returns A pre-typed `removeListener` with the state, dispatch and extra + * types already defined. * * @example * ```ts * import { removeListener } from '@reduxjs/toolkit' * - * export const removeAppListener = removeListener.withTypes() + * export const removeAppListener = removeListener.withTypes< + * RootState, + * AppDispatch, + * ExtraArguments + * >() * ``` * * @template OverrideStateType - The specific type of state the middleware listener operates on. * @template OverrideDispatchType - The specific type of the dispatch function. + * @template OverrideExtraArgument - The specific type of the extra object. * * @since 2.1.0 */ @@ -635,7 +645,8 @@ export type TypedRemoveListener< unknown, UnknownAction >, - >() => TypedRemoveListener + OverrideExtraArgument = unknown, + >() => TypedRemoveListener } /** @@ -660,13 +671,13 @@ export type TypedStartListening< /** * Creates a "pre-typed" version of * {@linkcode ListenerMiddlewareInstance.startListening startListening} - * where the `state` and `dispatch` types are predefined. + * where the `state`, `dispatch` and `extra` types are predefined. * - * This allows you to set the `state` and `dispatch` types once, + * This allows you to set the `state`, `dispatch` and `extra` types once, * eliminating the need to specify them with every * {@linkcode ListenerMiddlewareInstance.startListening startListening} call. * - * @returns A pre-typed `startListening` with the state and dispatch types already defined. + * @returns A pre-typed `startListening` with the state, dispatch and extra types already defined. * * @example * ```ts @@ -676,12 +687,14 @@ export type TypedStartListening< * * export const startAppListening = listenerMiddleware.startListening.withTypes< * RootState, - * AppDispatch + * AppDispatch, + * ExtraArguments * >() * ``` * * @template OverrideStateType - The specific type of state the middleware listener operates on. * @template OverrideDispatchType - The specific type of the dispatch function. + * @template OverrideExtraArgument - The specific type of the extra object. * * @since 2.1.0 */ @@ -692,7 +705,8 @@ export type TypedStartListening< unknown, UnknownAction >, - >() => TypedStartListening + OverrideExtraArgument = unknown, + >() => TypedStartListening } /** @@ -707,17 +721,18 @@ export type TypedStopListening< unknown, UnknownAction >, -> = RemoveListenerOverloads & { + ExtraArgument = unknown, +> = RemoveListenerOverloads & { /** * Creates a "pre-typed" version of * {@linkcode ListenerMiddlewareInstance.stopListening stopListening} - * where the `state` and `dispatch` types are predefined. + * where the `state`, `dispatch` and `extra` types are predefined. * - * This allows you to set the `state` and `dispatch` types once, + * This allows you to set the `state`, `dispatch` and `extra` types once, * eliminating the need to specify them with every * {@linkcode ListenerMiddlewareInstance.stopListening stopListening} call. * - * @returns A pre-typed `stopListening` with the state and dispatch types already defined. + * @returns A pre-typed `stopListening` with the state, dispatch and extra types already defined. * * @example * ```ts @@ -727,12 +742,14 @@ export type TypedStopListening< * * export const stopAppListening = listenerMiddleware.stopListening.withTypes< * RootState, - * AppDispatch + * AppDispatch, + * ExtraArguments * >() * ``` * * @template OverrideStateType - The specific type of state the middleware listener operates on. * @template OverrideDispatchType - The specific type of the dispatch function. + * @template OverrideExtraArgument - The specific type of the extra object. * * @since 2.1.0 */ @@ -743,7 +760,8 @@ export type TypedStopListening< unknown, UnknownAction >, - >() => TypedStopListening + OverrideExtraArgument = unknown, + >() => TypedStopListening } /** @@ -758,19 +776,22 @@ export type TypedCreateListenerEntry< unknown, UnknownAction >, + ExtraArgument = unknown, > = AddListenerOverloads< ListenerEntry, StateType, - DispatchType + DispatchType, + ExtraArgument > & { /** * Creates a "pre-typed" version of `createListenerEntry` - * where the `state` and `dispatch` types are predefined. + * where the `state`, `dispatch` and `extra` types are predefined. * - * This allows you to set the `state` and `dispatch` types once, eliminating + * This allows you to set the `state`, `dispatch` and `extra` types once, eliminating * the need to specify them with every `createListenerEntry` call. * - * @returns A pre-typed `createListenerEntry` with the state and dispatch types already defined. + * @returns A pre-typed `createListenerEntry` with the state, dispatch and extra + * types already defined. * * @example * ```ts @@ -778,12 +799,14 @@ export type TypedCreateListenerEntry< * * export const createAppListenerEntry = createListenerEntry.withTypes< * RootState, - * AppDispatch + * AppDispatch, + * ExtraArguments * >() * ``` * * @template OverrideStateType - The specific type of state the middleware listener operates on. * @template OverrideDispatchType - The specific type of the dispatch function. + * @template OverrideExtraArgument - The specific type of the extra object. * * @since 2.1.0 */ @@ -794,7 +817,8 @@ export type TypedCreateListenerEntry< unknown, UnknownAction >, - >() => TypedStopListening + OverrideExtraArgument = unknown, + >() => TypedStopListening } /**