Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: reduxjs/redux
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v5.0.0-rc.0
Choose a base ref
...
head repository: reduxjs/redux
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v5.0.0-rc.1
Choose a head ref
  • 16 commits
  • 10 files changed
  • 2 contributors

Commits on Nov 20, 2023

  1. Copy the full SHA
    8472642 View commit details
  2. tests

    EskiMojo14 committed Nov 20, 2023
    Copy the full SHA
    7859c01 View commit details
  3. use internal import

    EskiMojo14 committed Nov 20, 2023
    Copy the full SHA
    d44a074 View commit details
  4. Merge pull request #4620 from reduxjs/is-action-predicate

    Add isAction type predicate
    EskiMojo14 authored Nov 20, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    85d7f27 View commit details
  5. export isPlainObject

    EskiMojo14 committed Nov 20, 2023
    Copy the full SHA
    4cdafb6 View commit details
  6. Merge pull request #4621 from reduxjs:export-ipo

    export isPlainObject
    EskiMojo14 authored Nov 20, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    c9e0650 View commit details

Commits on Nov 23, 2023

  1. Copy the full SHA
    1437fcf View commit details
  2. Copy the full SHA
    c2abb27 View commit details
  3. Add missing error message

    markerikson committed Nov 23, 2023
    Copy the full SHA
    9501bc4 View commit details
  4. Copy the full SHA
    c609eb7 View commit details
  5. Copy the full SHA
    2b7af71 View commit details
  6. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    dae0da7 View commit details
  7. Copy the full SHA
    a2ae5ca View commit details
  8. Add lint check

    markerikson committed Nov 23, 2023
    Copy the full SHA
    cacf745 View commit details
  9. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e2e8fe9 View commit details
  10. Release 5.0.0-rc.1

    markerikson committed Nov 23, 2023
    Copy the full SHA
    0d7ef2c View commit details
Showing with 816 additions and 592 deletions.
  1. +32 −23 .github/workflows/test.yaml
  2. +2 −1 errors.json
  3. +1 −1 netlify.toml
  4. +11 −6 package.json
  5. +4 −0 src/index.ts
  6. +10 −0 src/utils/isAction.ts
  7. +1 −1 src/utils/isPlainObject.ts
  8. +22 −30 test/typescript/store.ts
  9. +23 −0 test/utils/isAction.spec.ts
  10. +710 −530 yarn.lock
55 changes: 32 additions & 23 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -29,7 +29,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node: ['16.x']
node: ['18.x']

steps:
- name: Checkout repo
@@ -44,6 +44,9 @@ jobs:
- name: Install deps
run: yarn install

- name: Lint
run: yarn lint

- name: Build
run: yarn build

@@ -62,7 +65,7 @@ jobs:
strategy:
fail-fast: false
matrix:
node: ['16.x']
node: ['18.x']
steps:
- name: Checkout repo
uses: actions/checkout@v2
@@ -99,8 +102,8 @@ jobs:
strategy:
fail-fast: false
matrix:
node: ['16.x']
ts: ['4.7', '4.8', '4.9', '5.0']
node: ['18.x']
ts: ['4.7', '4.8', '4.9', '5.0', '5.1', '5.2', '5.3']
steps:
- name: Checkout repo
uses: actions/checkout@v2
@@ -132,6 +135,28 @@ jobs:
yarn test:typecheck
yarn test:types
are-the-types-wrong:
name: Check package config with are-the-types-wrong

needs: [build]
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node: ['18.x']
steps:
- name: Checkout repo
uses: actions/checkout@v3

- uses: actions/download-artifact@v3
with:
name: package
path: .

# Note: We currently expect "FalseCJS" failures for Node16 + `moduleResolution: "node16"
- name: Run are-the-types-wrong
run: npx @arethetypeswrong/cli ./package.tgz --format table --ignore-rules false-cjs

test-published-artifact:
name: Test Published Artifact ${{ matrix.example }}

@@ -140,17 +165,8 @@ jobs:
strategy:
fail-fast: false
matrix:
node: ['16.x']
example:
[
'cra4',
'cra5',
'next',
'vite',
'node-standard',
'node-esm',
'are-the-types-wrong'
]
node: ['18.x']
example: ['cra4', 'cra5', 'next', 'vite', 'node-standard', 'node-esm']
steps:
- name: Checkout repo
uses: actions/checkout@v2
@@ -190,15 +206,8 @@ jobs:

- name: Build example
working-directory: ./redux-toolkit/examples/publish-ci/${{ matrix.example }}
run: yarn build
run: NODE_OPTIONS=--openssl-legacy-provider yarn build

- name: Run test step
working-directory: ./redux-toolkit/examples/publish-ci/${{ matrix.example }}
run: yarn test
if: matrix.example != 'are-the-types-wrong'

- name: Run test step
working-directory: ./redux-toolkit/examples/publish-ci/${{ matrix.example }}
# Ignore "FalseCJS" errors in the `attw` job
run: yarn test -n FalseCJS
if: matrix.example == 'are-the-types-wrong'
3 changes: 2 additions & 1 deletion errors.json
Original file line number Diff line number Diff line change
@@ -15,5 +15,6 @@
"13": "The slice reducer for key \"\" returned undefined when probed with a random type. Don't try to handle '' or other actions in \"redux/*\" namespace. They are considered private. Instead, you must return the current state for any unknown actions, unless it is undefined, in which case you must return the initial state, regardless of the action type. The initial state may not be undefined, but can be null.",
"14": "When called with an action of type , the slice reducer for key \"\" returned undefined. To ignore an action, you must explicitly return the previous state. If you want this reducer to hold no value, you can return null instead of undefined.",
"15": "Dispatching while constructing your middleware is not allowed. Other middleware would not be applied to this dispatch.",
"16": "bindActionCreators expected an object or a function, but instead received: ''. Did you write \"import ActionCreators from\" instead of \"import * as ActionCreators from\"?"
"16": "bindActionCreators expected an object or a function, but instead received: ''. Did you write \"import ActionCreators from\" instead of \"import * as ActionCreators from\"?",
"17": "Action \"type\" property must be a string. Instead, the actual type was: ''. Value was: '' (stringified)"
}
2 changes: 1 addition & 1 deletion netlify.toml
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@
ignore = "git diff --quiet HEAD^ HEAD -- ../docs/ ."

[build.environment]
NODE_VERSION = "16.14.0"
NODE_VERSION = "18.15.0"
NODE_OPTIONS = "--max_old_space_size=4096"
NETLIFY_USE_YARN = "true"
YARN_VERSION = "1.22.10"
17 changes: 11 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "redux",
"version": "5.0.0-rc.0",
"version": "5.0.0-rc.1",
"description": "Predictable state container for JavaScript apps",
"license": "MIT",
"homepage": "http://redux.js.org",
@@ -59,8 +59,8 @@
"devDependencies": {
"@babel/core": "^7.19.0",
"@types/node": "^18.7.16",
"@typescript-eslint/eslint-plugin": "^5.36.2",
"@typescript-eslint/parser": "^5.36.2",
"@typescript-eslint/eslint-plugin": "^6",
"@typescript-eslint/parser": "^6",
"cross-env": "^7.0.3",
"esbuild-extra": "^0.1.3",
"eslint": "^8.23.0",
@@ -74,9 +74,14 @@
"prettier": "^2.7.1",
"rimraf": "^3.0.2",
"rxjs": "^7.5.6",
"tsup": "^6.7.0",
"typescript": "^4.8.3",
"vitest": "^0.27.2"
"tsup": "7.0.0",
"typescript": "5.2",
"vitest": "^0.34.0"
},
"resolutions": {
"esbuild": "0.19.7",
"@typescript-eslint/eslint-plugin": "6.12.0",
"@typescript-eslint/parser": "6.12.0"
},
"sideEffects": false
}
4 changes: 4 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -4,6 +4,8 @@ import combineReducers from './combineReducers'
import bindActionCreators from './bindActionCreators'
import applyMiddleware from './applyMiddleware'
import compose from './compose'
import isAction from './utils/isAction'
import isPlainObject from './utils/isPlainObject'
import __DO_NOT_USE__ActionTypes from './utils/actionTypes'

// types
@@ -42,5 +44,7 @@ export {
bindActionCreators,
applyMiddleware,
compose,
isAction,
isPlainObject,
__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
@@ -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
52 changes: 22 additions & 30 deletions test/typescript/store.ts
Original file line number Diff line number Diff line change
@@ -69,11 +69,11 @@ const storeWithPreloadedState: Store<State> = createStore(reducer, {
b: { c: 'c', d: 'd' },
e: brandedString
})
// @ts-expect-error
const storeWithBadPreloadedState: Store<State> = createStore(reducer, {
b: { c: 'c' },
e: brandedString
})

const storeWithBadPreloadedState: Store<State> =
// @ts-expect-error
// prettier-ignore
createStore(reducer, { b: { c: 'c' }, e: brandedString })

const reducerA: Reducer<string> = (state = 'a') => state
const reducerB: Reducer<{ c: string; d: string }> = (
@@ -91,14 +91,11 @@ const storeWithCombineReducer = createStore(combinedReducer, {
b: { c: 'c', d: 'd' },
e: brandedString
})
// @ts-expect-error
const storeWithCombineReducerAndBadPreloadedState = createStore(
combinedReducer,
{
b: { c: 'c' },
e: brandedString
}
)

const storeWithCombineReducerAndBadPreloadedState =
// @ts-expect-error
// prettier-ignore
createStore( combinedReducer, { b: { c: 'c' }, e: brandedString } )

const nestedCombinedReducer = combineReducers({
a: (state: string = 'a') => state,
@@ -120,10 +117,10 @@ const simpleCombinedReducer = combineReducers({
d: (state: string = 'd') => state
})

// @ts-expect-error
const storeWithSimpleCombinedReducer = createStore(simpleCombinedReducer, {
c: 5
})
const storeWithSimpleCombinedReducer =
// @ts-expect-error
// prettier-ignore
createStore(simpleCombinedReducer, { c: 5 })

// Note: It's not necessary that the errors occur on the lines specified, just as long as something errors somewhere
// since the preloaded state doesn't match the reducer type.
@@ -133,11 +130,10 @@ const simpleCombinedReducerWithImplicitState = combineReducers({
d: (state = 'd') => state
})

// @ts-expect-error
const storeWithSimpleCombinedReducerWithImplicitState = createStore(
simpleCombinedReducerWithImplicitState,
{ c: 5 }
)
const storeWithSimpleCombinedReducerWithImplicitState =
// @ts-expect-error
// prettier-ignore
createStore( simpleCombinedReducerWithImplicitState, { c: 5 } )

const storeWithActionReducer = createStore(reducerWithAction)
const storeWithActionReducerAndPreloadedState = createStore(reducerWithAction, {
@@ -148,14 +144,10 @@ const storeWithActionReducerAndPreloadedState = createStore(reducerWithAction, {
funcWithStore(storeWithActionReducer)
funcWithStore(storeWithActionReducerAndPreloadedState)

// @ts-expect-error
const storeWithActionReducerAndBadPreloadedState = createStore(
reducerWithAction,
{
b: { c: 'c' },
e: brandedString
}
)
const storeWithActionReducerAndBadPreloadedState =
// @ts-expect-error
// prettier-ignore
createStore( reducerWithAction, { b: { c: 'c' }, e: brandedString } )

const enhancer: StoreEnhancer = next => next

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)
}
})
})
1,240 changes: 710 additions & 530 deletions yarn.lock

Large diffs are not rendered by default.