Skip to content

Commit

Permalink
Merge pull request #4620 from reduxjs/is-action-predicate
Browse files Browse the repository at this point in the history
Add isAction type predicate
  • Loading branch information
EskiMojo14 committed Nov 20, 2023
2 parents 6804e81 + d44a074 commit 85d7f27
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 1 deletion.
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import combineReducers from './combineReducers'
import bindActionCreators from './bindActionCreators'
import applyMiddleware from './applyMiddleware'
import compose from './compose'
import isAction from './utils/isAction'
import __DO_NOT_USE__ActionTypes from './utils/actionTypes'

// types
Expand Down Expand Up @@ -42,5 +43,6 @@ export {
bindActionCreators,
applyMiddleware,
compose,
isAction,
__DO_NOT_USE__ActionTypes
}
10 changes: 10 additions & 0 deletions src/utils/isAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Action } from '../types/actions'
import isPlainObject from './isPlainObject'

export default function isAction(action: unknown): action is Action<string> {
return (
isPlainObject(action) &&
'type' in action &&
typeof (action as Record<'type', unknown>).type === 'string'
)
}
2 changes: 1 addition & 1 deletion src/utils/isPlainObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @param obj The object to inspect.
* @returns True if the argument appears to be a plain object.
*/
export default function isPlainObject(obj: any): boolean {
export default function isPlainObject(obj: any): obj is object {
if (typeof obj !== 'object' || obj === null) return false

let proto = obj
Expand Down
23 changes: 23 additions & 0 deletions test/utils/isAction.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import isAction from '@internal/utils/isAction'

describe('isAction', () => {
it('should only return true for plain objects with a string type property', () => {
const actionCreator = () => ({ type: 'anAction' })
class Action {
type = 'totally an action'
}
const testCases: [action: unknown, expected: boolean][] = [
[{ type: 'an action' }, true],
[{ type: 'more props', extra: true }, true],
[{ type: 0 }, false],
[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)
}
})
})

0 comments on commit 85d7f27

Please sign in to comment.