diff --git a/packages/toolkit/src/createAction.ts b/packages/toolkit/src/createAction.ts index 0647a04621..ab52d1c4fc 100644 --- a/packages/toolkit/src/createAction.ts +++ b/packages/toolkit/src/createAction.ts @@ -224,7 +224,7 @@ export type PayloadActionCreator< * A utility function to create an action creator for the given action type * string. The action creator accepts a single argument, which will be included * in the action object as a field called payload. The action creator function - * will also have its toString() overriden so that it returns the action type, + * will also have its toString() overridden so that it returns the action type, * allowing it to be used in reducer logic that is looking for that action type. * * @param type The action type to use for created actions. @@ -241,7 +241,7 @@ export function createAction
(
* A utility function to create an action creator for the given action type
* string. The action creator accepts a single argument, which will be included
* in the action object as a field called payload. The action creator function
- * will also have its toString() overriden so that it returns the action type,
+ * will also have its toString() overridden so that it returns the action type,
* allowing it to be used in reducer logic that is looking for that action type.
*
* @param type The action type to use for created actions.
@@ -286,6 +286,16 @@ export function createAction(type: string, prepareAction?: Function): any {
return actionCreator
}
+/**
+ * Returns true if value is a plain object with a `type` property.
+ */
+export function isAction(action: unknown): action is Action =
(api) => (next) => (action) => {
+ if (!isAction(action)) {
+ // we only want to notify listeners for action objects
+ return next(action)
+ }
+
if (addListener.match(action)) {
return startListening(action.payload)
}
diff --git a/packages/toolkit/src/listenerMiddleware/tests/fork.test.ts b/packages/toolkit/src/listenerMiddleware/tests/fork.test.ts
index 2756e09f15..6d9e6abb56 100644
--- a/packages/toolkit/src/listenerMiddleware/tests/fork.test.ts
+++ b/packages/toolkit/src/listenerMiddleware/tests/fork.test.ts
@@ -367,7 +367,7 @@ describe('fork', () => {
},
})
- store.dispatch(increment)
+ store.dispatch(increment())
expect(await deferredResult).toBe(listenerCompleted)
})
diff --git a/packages/toolkit/src/tests/createAction.test.ts b/packages/toolkit/src/tests/createAction.test.ts
index b5e8b67b26..5b481b945c 100644
--- a/packages/toolkit/src/tests/createAction.test.ts
+++ b/packages/toolkit/src/tests/createAction.test.ts
@@ -1,4 +1,4 @@
-import { createAction, getType } from '@reduxjs/toolkit'
+import { createAction, getType, isAction } from '@reduxjs/toolkit'
describe('createAction', () => {
it('should create an action', () => {
@@ -122,6 +122,27 @@ describe('createAction', () => {
})
})
+describe('isAction', () => {
+ it('should only return true for plain objects with a type property', () => {
+ const actionCreator = createAction('anAction')
+ class Action {
+ type = 'totally an action'
+ }
+ const testCases: [action: unknown, expected: boolean][] = [
+ [{ type: 'an action' }, true],
+ [{ type: 'more props', extra: true }, true],
+ [actionCreator(), true],
+ [actionCreator, false],
+ [Promise.resolve({ type: 'an action' }), false],
+ [new Action(), false],
+ ['a string', false],
+ ]
+ for (const [action, expected] of testCases) {
+ expect(isAction(action)).toBe(expected)
+ }
+ })
+})
+
describe('getType', () => {
it('should return the action type', () => {
const actionCreator = createAction('A_TYPE')