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

Rewrite action listener middleware types for better DX #1730

Merged
merged 5 commits into from
Nov 13, 2021

Conversation

markerikson
Copy link
Collaborator

@markerikson markerikson commented Nov 12, 2021

This PR:

The major changes in API/DX are:

  • Both middleware.addListener and addListenerAction now take the exact same params - an options object containing the listener callback and when option, with five possible variations in how the middleware decides what actions will trigger the listener callback:
    • a plain action type string
    • an RTK action creator
    • an RTK "matcher" function
    • a "listener predicate" like (action, currentState, originalState) => boolean
    • a "listener predicate" which is also a type guard for the action
  • The common overloads are now extracted as a reusable type that accepts the right return value
  • It now exports TypedAddListener<State> and TypedAddListenerAction<State> types that can be used to create "pre-typed" versions of middleware.addListener and addListenerAction
  • There's a createListenerEntry function that does the real work of looking at the options and assembling a listener entry
  • createActionListenerMiddleware() defaults the state to unknown
  • The middleware now includes addListenerAction as one of its attached fields, which means that if you do createActionListenerMiddleware<MyState>(), then middleware.addListener/addListenerAction are pre-typed.

The net results are that it should be fairly straightforward for users to ensure proper typing for their listener callbacks with the right state and action types, similar to how we define "pre-typed" hooks.

The one thing that appears to be not working atm is that a ListenerPredicate of (action, currentState, previousState) : action is PayloadAction<number> => {} does not appear to be inferring the type of action in the listener callback (see test file line 813). You can see the failure in the test job run.

@github-actions
Copy link

github-actions bot commented Nov 12, 2021

size-limit report 📦

Path Size
1. entry point: @reduxjs/toolkit (cjs.production.min.js) 12.23 KB (0%)
1. entry point: @reduxjs/toolkit (esm.js) 10.22 KB (0%)
1. entry point: @reduxjs/toolkit/query (cjs.production.min.js) 20.35 KB (0%)
1. entry point: @reduxjs/toolkit/query (esm.js) 17.37 KB (0%)
1. entry point: @reduxjs/toolkit/query/react (cjs.production.min.js) 22.22 KB (0%)
1. entry point: @reduxjs/toolkit/query/react (esm.js) 19.82 KB (0%)
2. entry point: @reduxjs/toolkit (without dependencies) (cjs.production.min.js) 5.56 KB (0%)
2. entry point: @reduxjs/toolkit (without dependencies) (esm.js) 5.53 KB (0%)
2. entry point: @reduxjs/toolkit/query (without dependencies) (cjs.production.min.js) 9.2 KB (0%)
2. entry point: @reduxjs/toolkit/query (without dependencies) (esm.js) 9.58 KB (0%)
2. entry point: @reduxjs/toolkit/query/react (without dependencies) (cjs.production.min.js) 2.37 KB (0%)
2. entry point: @reduxjs/toolkit/query/react (without dependencies) (esm.js) 2.21 KB (0%)
3. createSlice (esm.js) 5.16 KB (0%)
3. createEntityAdapter (esm.js) 5.83 KB (0%)
3. configureStore (esm.js) 5.83 KB (0%)
3. createApi (esm.js) 15.66 KB (0%)
3. createApi (react) (esm.js) 18.05 KB (0%)
3. fetchBaseQuery (esm.js) 10.93 KB (0%)
3. setupListeners (esm.js) 9.8 KB (0%)
3. ApiProvider (esm.js) 16.99 KB (0%)

@codesandbox-ci
Copy link

codesandbox-ci bot commented Nov 12, 2021

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit d9ce0d4:

Sandbox Source
Vanilla Configuration
Vanilla Typescript Configuration
rsk-github-issues-example Configuration
@examples-query-react/basic Configuration
@examples-query-react/advanced Configuration

Comment on lines +191 to +199
<LP extends AnyActionListenerPredicate<S>>(
options: {
actionCreator?: never
type?: never
matcher?: never
predicate: LP
listener: ActionListener<AnyAction, S, D>
} & ActionListenerOptions
): Return
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll have to check on my computer to verify, but making this overload to be the first one on top should fix the state inference problem.

When I did that on my branch, I then saw a different error which I fixed using the ListenerPredicateGuardedActionType I put in there.

Copy link
Collaborator Author

@markerikson markerikson Nov 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I'm seeing is an action inference problem (which might be what you meant). I just tried moving this one up, and didn't see a difference.

FYI, I tried splitting up the predicate into two different versions: one for "it just returns a boolean", and one for "it's actually a type guard", since that seemed to make TS happier.

I did already grab LPGuardedActionType from your branch over to here.

@markerikson
Copy link
Collaborator Author

I will poke at this a bit further, but this is a big enough improvement I'm inclined to just comment out the one failing typetest and ship this as 0.3. (assuming the package changes work as intended as well.)

@markerikson
Copy link
Collaborator Author

I'm sorta figuring out why this is failing. The ListenerPredicate<Action, State. type doesn't seem match unless you explicitly declare the argument types in your predicate?

No types declared:

image

With explicit types:

image

I suppose the question is if there's any way to get the predicate to kick in even if there's no explicit args declared...?

@markerikson markerikson force-pushed the feature/listener-types-improvements branch from c11d8fd to d9ce0d4 Compare November 13, 2021 03:30
@markerikson
Copy link
Collaborator Author

Going to merge this as-is. I've got some other functionality I want to work on now that the types are basically in place.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants