-
Notifications
You must be signed in to change notification settings - Fork 674
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
Allow Differently Typed Selectors #274
Conversation
This is a breaking change since generic arguments changed. We should include both old and new signatures. |
@aikoven Yep! Added them back |
I've tested these against a fairly large project with lots of selectors and it worked fine. There's a failing test that should be fixed. Also, I guess some tests for the new signatures should be added as well. |
@aikoven Cool! I fixed the broken tests and added both a failing-case and a passing-case test for both parametric and array selectors |
Codecov Report
@@ Coverage Diff @@
## master #274 +/- ##
=====================================
Coverage 100% 100%
=====================================
Files 1 1
Lines 15 15
=====================================
Hits 15 15 Continue to review full report at Codecov.
|
Also, I put the Python script I threw together into a Gist - in case someone wants to refer back to this and change the types at some point https://gist.github.com/benshope/9712ed6d725a263467447ac6473502a9 |
Nice work @benshope! It's 👍 to me, I hope someone else would also test these in their projects. |
@aikoven I tacked on an additional commit to this PR to cover typescript 2.4's new strict generic checks and added a test here: 5ec2b1f You can see relevant discussion on the topic in this typescript issue: microsoft/TypeScript#17509 |
2 similar comments
Changing the generic signature of It could potentially be solved via generic defaults, although it would break for users of TS 2.2 and below. |
This reverts commit 5ec2b1f.
That's fair, I hadn't considered the case where some one might be calling defualtMemoize<MyFunction> I've reverted the commit. |
@aikoven Hey! Any updates on the status of this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@benshope I am so sorry, I've completely lost this thread.
As far as I can remember and see, these changes are backward compatible, aren't they?
Approving.
@aikoven Cool! Yes these changes should be backwards compatible |
Sorry to be so slow to this. As @aikoven has approved, I'll go ahead and commit. Thanks! |
@ellbee Thanks!! |
… support (#29094) ## Motivation #### Homogenous selector types: ```ts const selectorOne = (state: State) => state.something; const selectorTwo = (state: State) => state.other; createSelector([selectorOne, selectorTwo], () => ...); ``` #### Heterogenous selector types: ```ts const selectorOne = (state: { something: string }) => state.something; const selectorTwo = (state: { other: number }) => state.other; createSelector([selectorOne, selectorTwo], () => ...); ``` Support for heterogenous typing is essential for selectors to function properly, because selectors must be both mergeable and atomic. Without heterogenous selectors, these becoming conflicting objectives. - **Mergeable:** - Without heterogenous typing for selectors, the size of the state type for all selectors tend to inflate. This is because a selector's state must be a supertype for the intersection of the state types of all of its merged selectors, including selectors nested in the definitions of merged selectors. - Eventually, many selectors end up being defined with a state type that is close to the entire Redux state. - Paradoxically, selectors that only need access to very few properties end up needing to have the widest state type, because they tend to be merged into the most selectors across several nested levels. - **Atomic:** - When selectors are actually invoked, including in test files, it's not always practical to prepare and pass in a very large state object. - It's both safer and more convenient to restrict the state being passed into the selector to the minimum size required for the selector to function. - This requirement becomes incompatible with the mergeability requirement if all selectors must share a common state type. Enabling merged selectors to accept different, even disjoint state types resolves this issue. > [!NOTE] > See the [`MultichainState`](https://github.com/MetaMask/metamask-extension/blob/4f970df0acec3e3bc80da08373aa3b16f23aae41/ui/selectors/multichain.ts#L53) type for an example of a bloated selector state type which will become unnecessary with this update. ## **Description** - `reselect@4.0.0` supports heterogenous typing for selector inputs to `createSelector` and `createDeepEqualSelector`. - reduxjs/reselect#351 - reduxjs/reselect#274 - reduxjs/reselect#315 - Upgrade to `^5.1.1` (latest) is necessary to fix type issues in `4.0.0` - https://app.circleci.com/jobs/github/MetaMask/metamask-extension/4320173 [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/29094?quickstart=1) ## **Related issues** - Blocks TypeScript conversion of selectors for MetaMask/MetaMask-planning#2894. - #29014 ## **Manual testing steps** ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --------- Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
… support (#29094) ## Motivation #### Homogenous selector types: ```ts const selectorOne = (state: State) => state.something; const selectorTwo = (state: State) => state.other; createSelector([selectorOne, selectorTwo], () => ...); ``` #### Heterogenous selector types: ```ts const selectorOne = (state: { something: string }) => state.something; const selectorTwo = (state: { other: number }) => state.other; createSelector([selectorOne, selectorTwo], () => ...); ``` Support for heterogenous typing is essential for selectors to function properly, because selectors must be both mergeable and atomic. Without heterogenous selectors, these becoming conflicting objectives. - **Mergeable:** - Without heterogenous typing for selectors, the size of the state type for all selectors tend to inflate. This is because a selector's state must be a supertype for the intersection of the state types of all of its merged selectors, including selectors nested in the definitions of merged selectors. - Eventually, many selectors end up being defined with a state type that is close to the entire Redux state. - Paradoxically, selectors that only need access to very few properties end up needing to have the widest state type, because they tend to be merged into the most selectors across several nested levels. - **Atomic:** - When selectors are actually invoked, including in test files, it's not always practical to prepare and pass in a very large state object. - It's both safer and more convenient to restrict the state being passed into the selector to the minimum size required for the selector to function. - This requirement becomes incompatible with the mergeability requirement if all selectors must share a common state type. Enabling merged selectors to accept different, even disjoint state types resolves this issue. > [!NOTE] > See the [`MultichainState`](https://github.com/MetaMask/metamask-extension/blob/4f970df0acec3e3bc80da08373aa3b16f23aae41/ui/selectors/multichain.ts#L53) type for an example of a bloated selector state type which will become unnecessary with this update. ## **Description** - `reselect@4.0.0` supports heterogenous typing for selector inputs to `createSelector` and `createDeepEqualSelector`. - reduxjs/reselect#351 - reduxjs/reselect#274 - reduxjs/reselect#315 - Upgrade to `^5.1.1` (latest) is necessary to fix type issues in `4.0.0` - https://app.circleci.com/jobs/github/MetaMask/metamask-extension/4320173 [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/29094?quickstart=1) ## **Related issues** - Blocks TypeScript conversion of selectors for MetaMask/MetaMask-planning#2894. - #29014 ## **Manual testing steps** ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --------- Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
Here is the related issue #264
Right now we have to do typings like this:
This PR allows us to do typings like this:
Let me know if I should change anything, thanks!