Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Adds ExtraArgument to withTypes for listenerMiddleware. #4517

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
feat: Adds ExtraArgument to withTypes for listenerMiddleware.
These changes are based upon the changes in introduction of withTypes for the listenerMiddleware.
antondalgren committed Jul 17, 2024

Verified

This commit was signed with the committer’s verified signature.
sandhose Quentin Gliech
commit e1256f3789b97c932ab2200d9de05d410db023fa
5 changes: 4 additions & 1 deletion docs/api/createListenerMiddleware.mdx
Original file line number Diff line number Diff line change
@@ -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<RootState, AppDispatch>()
Original file line number Diff line number Diff line change
@@ -64,6 +64,7 @@ type AppThunk<ThunkReturnType = void> = ThunkAction<
unknown,
Action
>
type ExtraArgument = { foo: string }

describe('listenerMiddleware.withTypes<RootState, AppDispatch>()', () => {
const listenerMiddleware = createListenerMiddleware()
@@ -77,11 +78,12 @@ describe('listenerMiddleware.withTypes<RootState, AppDispatch>()', () => {
test('startListening.withTypes', () => {
const startAppListening = listenerMiddleware.startListening.withTypes<
RootState,
AppDispatch
AppDispatch,
ExtraArgument
>()

expectTypeOf(startAppListening).toEqualTypeOf<
TypedStartListening<RootState, AppDispatch>
TypedStartListening<RootState, AppDispatch, ExtraArgument>
>()

startAppListening({
@@ -102,6 +104,8 @@ describe('listenerMiddleware.withTypes<RootState, AppDispatch>()', () => {

expectTypeOf(stateCurrent).toEqualTypeOf<RootState>()

expectTypeOf(listenerApi.extra).toEqualTypeOf<ExtraArgument>()

timeout = 1
takeResult = await listenerApi.take(increment.match, timeout)

@@ -111,10 +115,10 @@ describe('listenerMiddleware.withTypes<RootState, AppDispatch>()', () => {
})

test('addListener.withTypes', () => {
const addAppListener = addListener.withTypes<RootState, AppDispatch>()
const addAppListener = addListener.withTypes<RootState, AppDispatch, ExtraArgument>()

expectTypeOf(addAppListener).toEqualTypeOf<
TypedAddListener<RootState, AppDispatch>
TypedAddListener<RootState, AppDispatch, ExtraArgument>
>()

store.dispatch(
@@ -126,27 +130,30 @@ describe('listenerMiddleware.withTypes<RootState, AppDispatch>()', () => {
expectTypeOf(state).toEqualTypeOf<RootState>()

expectTypeOf(listenerApi.dispatch).toEqualTypeOf<AppDispatch>()

expectTypeOf(listenerApi.extra).toEqualTypeOf<ExtraArgument>()
},
}),
)
})

test('removeListener.withTypes', () => {
const removeAppListener = removeListener.withTypes<RootState, AppDispatch>()
const removeAppListener = removeListener.withTypes<RootState, AppDispatch, ExtraArgument>()

expectTypeOf(removeAppListener).toEqualTypeOf<
TypedRemoveListener<RootState, AppDispatch>
TypedRemoveListener<RootState, AppDispatch, ExtraArgument>
>()
})

test('stopListening.withTypes', () => {
const stopAppListening = listenerMiddleware.stopListening.withTypes<
RootState,
AppDispatch
AppDispatch,
ExtraArgument
>()

expectTypeOf(stopAppListening).toEqualTypeOf<
TypedStopListening<RootState, AppDispatch>
TypedStopListening<RootState, AppDispatch, ExtraArgument>
>()
})
})
Original file line number Diff line number Diff line change
@@ -55,21 +55,25 @@ type AppThunk<ThunkReturnType = void> = 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<RootState, AppDispatch>()
const addAppListener = addListener.withTypes<RootState, AppDispatch, ExtraArgument>()

const removeAppListener = removeListener.withTypes<RootState, AppDispatch>()
const removeAppListener = removeListener.withTypes<RootState, AppDispatch, ExtraArgument>()

describe('startAppListening.withTypes', () => {
test('should return startListening', () => {
84 changes: 54 additions & 30 deletions packages/toolkit/src/listenerMiddleware/types.ts
Original file line number Diff line number Diff line change
@@ -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<RootState, AppDispatch>()
* export const addAppListener = addListener.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
*/
@@ -581,8 +583,9 @@ export type TypedAddListener<
OverrideStateType,
unknown,
UnknownAction
>,
>() => TypedAddListener<OverrideStateType, OverrideDispatchType>
>,
OverrideExtraArgument = unknown,
>() => TypedAddListener<OverrideStateType, OverrideDispatchType, OverrideExtraArgument>
}

/**
@@ -597,34 +600,41 @@ export type TypedRemoveListener<
unknown,
UnknownAction
>,
ExtraArgument = unknown,
Payload = ListenerEntry<StateType, DispatchType>,
T extends string = 'listenerMiddleware/remove',
> = BaseActionCreator<Payload, T> &
AddListenerOverloads<
PayloadAction<Payload, T>,
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<RootState, AppDispatch>()
* 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<OverrideStateType, OverrideDispatchType>
OverrideExtraArgument = unknown,
>() => TypedRemoveListener<OverrideStateType, OverrideDispatchType, OverrideExtraArgument>
}

/**
@@ -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<OverrideStateType, OverrideDispatchType>
OverrideExtraArgument = unknown,
>() => TypedStartListening<OverrideStateType, OverrideDispatchType, OverrideExtraArgument>
}

/**
@@ -707,17 +721,18 @@ export type TypedStopListening<
unknown,
UnknownAction
>,
> = RemoveListenerOverloads<StateType, DispatchType> & {
ExtraArgument = unknown,
> = RemoveListenerOverloads<StateType, DispatchType, ExtraArgument> & {
/**
* 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<OverrideStateType, OverrideDispatchType>
OverrideExtraArgument = unknown,
>() => TypedStopListening<OverrideStateType, OverrideDispatchType, OverrideExtraArgument>
}

/**
@@ -758,32 +776,37 @@ export type TypedCreateListenerEntry<
unknown,
UnknownAction
>,
ExtraArgument = unknown,
> = AddListenerOverloads<
ListenerEntry<StateType, DispatchType>,
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
* import { createListenerEntry } from '@reduxjs/toolkit'
*
* 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<OverrideStateType, OverrideDispatchType>
OverrideExtraArgument = unknown,
>() => TypedStopListening<OverrideStateType, OverrideDispatchType, OverrideExtraArgument>
}

/**