From b4439a931632c10cc57d66818b2690ce08d50e3d Mon Sep 17 00:00:00 2001 From: Arya Emami Date: Wed, 3 Jan 2024 18:33:48 -0600 Subject: [PATCH 01/20] Add initial implementation of `createStructuredSelector.withTypes` --- src/createStructuredSelector.ts | 84 ++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 37 deletions(-) diff --git a/src/createStructuredSelector.ts b/src/createStructuredSelector.ts index a16e395a1..b71c188c6 100644 --- a/src/createStructuredSelector.ts +++ b/src/createStructuredSelector.ts @@ -207,8 +207,8 @@ export type TypedStructuredSelectorCreator = * * @public */ -export interface SelectorsObject { - [key: string]: Selector +export interface SelectorsObject { + [key: string]: Selector } /** @@ -220,7 +220,7 @@ export interface SelectorsObject { * * @public */ -export type StructuredSelectorCreator = +export interface StructuredSelectorCreator { /** * A convenience function that simplifies returning an object * made up of selector results. @@ -327,7 +327,7 @@ export type StructuredSelectorCreator = * @see {@link https://reselect.js.org/api/createStructuredSelector `createStructuredSelector`} */ < - InputSelectorsObject extends SelectorsObject, + InputSelectorsObject extends SelectorsObject, MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize, ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize >( @@ -336,7 +336,7 @@ export type StructuredSelectorCreator = MemoizeFunction, ArgsMemoizeFunction > - ) => OutputSelector< + ): OutputSelector< ObjectValuesToTuple, Simplify>, MemoizeFunction, @@ -344,6 +344,10 @@ export type StructuredSelectorCreator = > & InterruptRecursion + withTypes< + OverrideStateType extends StateType + >(): StructuredSelectorCreator +} /** * A convenience function that simplifies returning an object * made up of selector results. @@ -394,35 +398,41 @@ export type StructuredSelectorCreator = * * @public */ -export const createStructuredSelector: StructuredSelectorCreator = (< - InputSelectorsObject extends SelectorsObject, - MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize, - ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize ->( - inputSelectorsObject: InputSelectorsObject, - selectorCreator: CreateSelectorFunction< - MemoizeFunction, - ArgsMemoizeFunction - > = createSelector as CreateSelectorFunction< - MemoizeFunction, - ArgsMemoizeFunction - > -) => { - assertIsObject( - inputSelectorsObject, - 'createStructuredSelector expects first argument to be an object ' + - `where each property is a selector, instead received a ${typeof inputSelectorsObject}` - ) - const inputSelectorKeys = Object.keys(inputSelectorsObject) - const dependencies = inputSelectorKeys.map(key => inputSelectorsObject[key]) - const structuredSelector = selectorCreator( - dependencies, - (...inputSelectorResults: any[]) => { - return inputSelectorResults.reduce((composition, value, index) => { - composition[inputSelectorKeys[index]] = value - return composition - }, {}) - } - ) - return structuredSelector -}) as StructuredSelectorCreator +export const createStructuredSelector: StructuredSelectorCreator = + Object.assign( + < + InputSelectorsObject extends SelectorsObject, + MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize, + ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize + >( + inputSelectorsObject: InputSelectorsObject, + selectorCreator: CreateSelectorFunction< + MemoizeFunction, + ArgsMemoizeFunction + > = createSelector as CreateSelectorFunction< + MemoizeFunction, + ArgsMemoizeFunction + > + ) => { + assertIsObject( + inputSelectorsObject, + 'createStructuredSelector expects first argument to be an object ' + + `where each property is a selector, instead received a ${typeof inputSelectorsObject}` + ) + const inputSelectorKeys = Object.keys(inputSelectorsObject) + const dependencies = inputSelectorKeys.map( + key => inputSelectorsObject[key] + ) + const structuredSelector = selectorCreator( + dependencies, + (...inputSelectorResults: any[]) => { + return inputSelectorResults.reduce((composition, value, index) => { + composition[inputSelectorKeys[index]] = value + return composition + }, {}) + } + ) + return structuredSelector + }, + { withTypes: () => createStructuredSelector } + ) as StructuredSelectorCreator From 0f6bb10d2a253bab1897c846f8ad9a98468f215d Mon Sep 17 00:00:00 2001 From: Arya Emami Date: Wed, 3 Jan 2024 18:34:08 -0600 Subject: [PATCH 02/20] Add type tests for `createStructuredSelector.withTypes` --- ...eateStructuredSelector.withTypes.test-d.ts | 186 ++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 type-tests/createStructuredSelector.withTypes.test-d.ts diff --git a/type-tests/createStructuredSelector.withTypes.test-d.ts b/type-tests/createStructuredSelector.withTypes.test-d.ts new file mode 100644 index 000000000..a2f23afaa --- /dev/null +++ b/type-tests/createStructuredSelector.withTypes.test-d.ts @@ -0,0 +1,186 @@ +import microMemoize from 'micro-memoize' +import { + createSelectorCreator, + createStructuredSelector, + lruMemoize, + weakMapMemoize +} from 'reselect' +import { describe, expectTypeOf, test } from 'vitest' + +interface Todo { + id: number + completed: boolean +} + +interface Alert { + id: number + read: boolean +} + +interface RootState { + todos: Todo[] + alerts: Alert[] +} + +const rootState: RootState = { + todos: [ + { id: 0, completed: false }, + { id: 1, completed: false } + ], + alerts: [ + { id: 0, read: false }, + { id: 1, read: false } + ] +} + +describe('createStructuredSelector.withTypes()', () => { + const createStructuredAppSelector = + createStructuredSelector.withTypes() + + test('locks down state type and infers types correctly', () => { + const structuredAppSelector = createStructuredAppSelector({ + todos: state => { + expectTypeOf(state).toEqualTypeOf(rootState) + + return state.todos + }, + alerts: state => { + expectTypeOf(state).toEqualTypeOf(rootState) + + return state.alerts + } + }) + const { todos, alerts } = structuredAppSelector(rootState) + + expectTypeOf(todos).toEqualTypeOf() + + expectTypeOf(alerts).toEqualTypeOf() + + expectTypeOf(structuredAppSelector.argsMemoize).toEqualTypeOf< + typeof weakMapMemoize + >(weakMapMemoize) + + expectTypeOf(structuredAppSelector.memoize).toEqualTypeOf< + typeof weakMapMemoize + >(weakMapMemoize) + + expectTypeOf(structuredAppSelector.clearCache).returns.toBeVoid() + + expectTypeOf(structuredAppSelector.clearCache).parameters.toEqualTypeOf< + [] + >() + + expectTypeOf(structuredAppSelector.dependencies).items.toBeFunction() + + expectTypeOf(structuredAppSelector.dependencyRecomputations).toEqualTypeOf< + () => number + >() + + expectTypeOf(structuredAppSelector.recomputations).toEqualTypeOf< + () => number + >() + + expectTypeOf( + structuredAppSelector.resetDependencyRecomputations + ).toEqualTypeOf<() => void>() + + expectTypeOf(structuredAppSelector.resetRecomputations).toEqualTypeOf< + () => void + >() + + expectTypeOf( + structuredAppSelector.lastResult + ).returns.toEqualTypeOf(rootState) + + expectTypeOf( + structuredAppSelector.memoizedResultFunc + ).parameters.toEqualTypeOf<[Todo[], Alert[]]>([ + rootState.todos, + rootState.alerts + ]) + + expectTypeOf( + structuredAppSelector.memoizedResultFunc + ).returns.toEqualTypeOf< + ReturnType + >(structuredAppSelector.lastResult()) + + expectTypeOf(structuredAppSelector.memoizedResultFunc).toHaveProperty( + 'clearCache' + ) + + expectTypeOf(structuredAppSelector.resultFunc).returns.toEqualTypeOf< + ReturnType + >(structuredAppSelector.lastResult()) + }) + + test('should correctly infer memoize and argsMemoize', () => { + const createSelectorLru = createSelectorCreator({ + memoize: lruMemoize, + argsMemoize: microMemoize + }) + + const structuredSelector = createStructuredAppSelector( + { + todos: state => state.todos, + alerts: state => state.alerts + }, + createSelectorLru + ) + + expectTypeOf(structuredSelector.argsMemoize).toEqualTypeOf< + typeof microMemoize + >(microMemoize) + + expectTypeOf(structuredSelector.memoize).toEqualTypeOf( + lruMemoize + ) + + const { todos, alerts } = structuredSelector(rootState) + + expectTypeOf(todos).toEqualTypeOf() + + expectTypeOf(alerts).toEqualTypeOf() + + expectTypeOf(structuredSelector.dependencies).items.toBeFunction() + + expectTypeOf(structuredSelector.dependencyRecomputations).toEqualTypeOf< + () => number + >() + + expectTypeOf(structuredSelector.recomputations).toEqualTypeOf< + () => number + >() + + expectTypeOf( + structuredSelector.resetDependencyRecomputations + ).toEqualTypeOf<() => void>() + + expectTypeOf(structuredSelector.resetRecomputations).toEqualTypeOf< + () => void + >() + + expectTypeOf( + structuredSelector.lastResult + ).returns.toEqualTypeOf(rootState) + + expectTypeOf( + structuredSelector.memoizedResultFunc + ).parameters.toEqualTypeOf<[Todo[], Alert[]]>([ + rootState.todos, + rootState.alerts + ]) + + expectTypeOf(structuredSelector.memoizedResultFunc).returns.toEqualTypeOf< + ReturnType + >(structuredSelector.lastResult()) + + expectTypeOf(structuredSelector.memoizedResultFunc).toHaveProperty( + 'clearCache' + ) + + expectTypeOf(structuredSelector.resultFunc).returns.toEqualTypeOf< + ReturnType + >(structuredSelector.lastResult()) + }) +}) From d3464d85fb02f3a8ceeafcbf8326274007947e7e Mon Sep 17 00:00:00 2001 From: Arya Emami Date: Wed, 3 Jan 2024 18:34:17 -0600 Subject: [PATCH 03/20] Add runtime unit tests for `createStructuredSelector.withTypes` --- ...createStructuredSelector.withTypes.test.ts | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 test/createStructuredSelector.withTypes.test.ts diff --git a/test/createStructuredSelector.withTypes.test.ts b/test/createStructuredSelector.withTypes.test.ts new file mode 100644 index 000000000..bcdb30816 --- /dev/null +++ b/test/createStructuredSelector.withTypes.test.ts @@ -0,0 +1,27 @@ +import { createStructuredSelector } from 'reselect' +import type { RootState } from './testUtils' +import { localTest } from './testUtils' + +describe(createStructuredSelector.withTypes, () => { + const createTypedStructuredSelector = + createStructuredSelector.withTypes() + + localTest('should return createStructuredSelector', ({ state }) => { + expect(createTypedStructuredSelector.withTypes).to.be.a('function') + + expect(createTypedStructuredSelector.withTypes().withTypes).to.be.a( + 'function' + ) + + expect(createTypedStructuredSelector).toBe(createStructuredSelector) + + const structuredSelector = createTypedStructuredSelector({ + todos: state => state.todos, + alerts: state => state.alerts + }) + + expect(structuredSelector).toBeMemoizedSelector() + + expect(structuredSelector(state)).to.be.an('object').that.is.not.empty + }) +}) From 605e46a767769c340bc2603c1589d05a0f0597de Mon Sep 17 00:00:00 2001 From: Arya Emami Date: Wed, 3 Jan 2024 18:46:36 -0600 Subject: [PATCH 04/20] Add additional type tests for `createStructuredSelector.withTypes` --- ...eateStructuredSelector.withTypes.test-d.ts | 181 ++++++++++++++++++ 1 file changed, 181 insertions(+) diff --git a/type-tests/createStructuredSelector.withTypes.test-d.ts b/type-tests/createStructuredSelector.withTypes.test-d.ts index a2f23afaa..2979e15f7 100644 --- a/type-tests/createStructuredSelector.withTypes.test-d.ts +++ b/type-tests/createStructuredSelector.withTypes.test-d.ts @@ -1,4 +1,5 @@ import microMemoize from 'micro-memoize' +import type { Selector, TypedStructuredSelectorCreator } from 'reselect' import { createSelectorCreator, createStructuredSelector, @@ -183,4 +184,184 @@ describe('createStructuredSelector.withTypes()', () => { ReturnType >(structuredSelector.lastResult()) }) + + test('supports additional parameters', () => { + const structuredAppSelector = createStructuredAppSelector({ + todos: state => { + expectTypeOf(state).toEqualTypeOf(rootState) + + return state.todos + }, + alerts: state => { + expectTypeOf(state).toEqualTypeOf(rootState) + + return state.alerts + }, + todoById: (state, id: number) => { + expectTypeOf(state).toEqualTypeOf(rootState) + + return state.todos[id] + } + }) + + const { alerts, todos, todoById } = structuredAppSelector(rootState, 0) + + expectTypeOf(todos).toEqualTypeOf() + + expectTypeOf(alerts).toEqualTypeOf() + + expectTypeOf(todoById).toEqualTypeOf() + + expectTypeOf(structuredAppSelector.argsMemoize).toEqualTypeOf< + typeof weakMapMemoize + >(weakMapMemoize) + + expectTypeOf(structuredAppSelector.memoize).toEqualTypeOf< + typeof weakMapMemoize + >(weakMapMemoize) + + expectTypeOf(structuredAppSelector.clearCache).returns.toBeVoid() + + expectTypeOf(structuredAppSelector.clearCache).parameters.toEqualTypeOf< + [] + >() + + expectTypeOf(structuredAppSelector.dependencies).items.toMatchTypeOf< + Selector + >() + + expectTypeOf(structuredAppSelector.dependencyRecomputations).toEqualTypeOf< + () => number + >() + + expectTypeOf(structuredAppSelector.recomputations).toEqualTypeOf< + () => number + >() + + expectTypeOf( + structuredAppSelector.resetDependencyRecomputations + ).returns.toBeVoid() + + expectTypeOf( + structuredAppSelector.resetDependencyRecomputations + ).parameters.items.toBeNever() + + expectTypeOf(structuredAppSelector.resetRecomputations).returns.toBeVoid() + + expectTypeOf( + structuredAppSelector.resetRecomputations + ).parameters.items.toBeNever() + + // Use `.branded` for intersection types https://github.com/mmkal/expect-type#why-is-my-assertion-failing + expectTypeOf( + structuredAppSelector.lastResult + ).returns.branded.toEqualTypeOf() + + expectTypeOf( + structuredAppSelector.memoizedResultFunc + ).parameters.toEqualTypeOf<[Todo[], Alert[], Todo]>([ + rootState.todos, + rootState.alerts, + rootState.todos[0] + ]) + + expectTypeOf(structuredAppSelector.resultFunc).parameters.toEqualTypeOf< + [Todo[], Alert[], Todo] + >([rootState.todos, rootState.alerts, rootState.todos[0]]) + + expectTypeOf( + structuredAppSelector.memoizedResultFunc + ).returns.toEqualTypeOf< + ReturnType + >(structuredAppSelector.lastResult()) + + expectTypeOf(structuredAppSelector.memoizedResultFunc).toHaveProperty( + 'clearCache' + ) + + expectTypeOf(structuredAppSelector.resultFunc).returns.toEqualTypeOf< + ReturnType + >(structuredAppSelector.lastResult()) + }) + + test('should work alongside TypedStructuredSelectorCreator', () => { + const createStructuredAppSelector: TypedStructuredSelectorCreator = + createStructuredSelector.withTypes() + + const structuredAppSelector = createStructuredAppSelector({ + todos: state => { + expectTypeOf(state).toEqualTypeOf(rootState) + + return state.todos + }, + alerts: state => { + expectTypeOf(state).toEqualTypeOf(rootState) + + return state.alerts + } + }) + + const { todos, alerts } = structuredAppSelector(rootState) + + expectTypeOf(todos).toEqualTypeOf() + + expectTypeOf(alerts).toEqualTypeOf() + + expectTypeOf(structuredAppSelector.argsMemoize).toEqualTypeOf< + typeof weakMapMemoize + >(weakMapMemoize) + + expectTypeOf(structuredAppSelector.memoize).toEqualTypeOf< + typeof weakMapMemoize + >(weakMapMemoize) + + expectTypeOf(structuredAppSelector.clearCache).returns.toBeVoid() + + expectTypeOf(structuredAppSelector.clearCache).parameters.toEqualTypeOf< + [] + >() + + expectTypeOf(structuredAppSelector.dependencies).items.toBeFunction() + + expectTypeOf(structuredAppSelector.dependencyRecomputations).toEqualTypeOf< + () => number + >() + + expectTypeOf(structuredAppSelector.recomputations).toEqualTypeOf< + () => number + >() + + expectTypeOf( + structuredAppSelector.resetDependencyRecomputations + ).toEqualTypeOf<() => void>() + + expectTypeOf(structuredAppSelector.resetRecomputations).toEqualTypeOf< + () => void + >() + + expectTypeOf( + structuredAppSelector.lastResult + ).returns.toEqualTypeOf(rootState) + + expectTypeOf( + structuredAppSelector.memoizedResultFunc + ).parameters.toEqualTypeOf<[Todo[], Alert[]]>([ + rootState.todos, + rootState.alerts + ]) + + expectTypeOf( + structuredAppSelector.memoizedResultFunc + ).returns.toEqualTypeOf< + ReturnType + >(structuredAppSelector.lastResult()) + + expectTypeOf(structuredAppSelector.memoizedResultFunc).toHaveProperty( + 'clearCache' + ) + + expectTypeOf(structuredAppSelector.resultFunc).returns.toEqualTypeOf< + ReturnType + >(structuredAppSelector.lastResult()) + }) }) From d9fcb157db3e5f79db301d4334bdd045b751fb08 Mon Sep 17 00:00:00 2001 From: Arya Emami Date: Wed, 3 Jan 2024 19:15:55 -0600 Subject: [PATCH 05/20] Add type tests for `StructuredSelectorCreator` --- ...eateStructuredSelector.withTypes.test-d.ts | 173 +++++++++++++++++- 1 file changed, 172 insertions(+), 1 deletion(-) diff --git a/type-tests/createStructuredSelector.withTypes.test-d.ts b/type-tests/createStructuredSelector.withTypes.test-d.ts index 2979e15f7..a3ba802d9 100644 --- a/type-tests/createStructuredSelector.withTypes.test-d.ts +++ b/type-tests/createStructuredSelector.withTypes.test-d.ts @@ -1,6 +1,11 @@ import microMemoize from 'micro-memoize' -import type { Selector, TypedStructuredSelectorCreator } from 'reselect' +import type { + Selector, + StructuredSelectorCreator, + TypedStructuredSelectorCreator +} from 'reselect' import { + createSelector, createSelectorCreator, createStructuredSelector, lruMemoize, @@ -51,6 +56,7 @@ describe('createStructuredSelector.withTypes()', () => { return state.alerts } }) + const { todos, alerts } = structuredAppSelector(rootState) expectTypeOf(todos).toEqualTypeOf() @@ -364,4 +370,169 @@ describe('createStructuredSelector.withTypes()', () => { ReturnType >(structuredAppSelector.lastResult()) }) + + test('should work with createSelector.withTypes()', () => { + const structuredAppSelector = createStructuredAppSelector( + { + todos: state => { + expectTypeOf(state).toEqualTypeOf(rootState) + + return state.todos + }, + alerts: state => { + expectTypeOf(state).toEqualTypeOf(rootState) + + return state.alerts + } + }, + createSelector.withTypes() + ) + + const { todos, alerts } = structuredAppSelector(rootState) + + expectTypeOf(todos).toEqualTypeOf() + + expectTypeOf(alerts).toEqualTypeOf() + + expectTypeOf(structuredAppSelector.argsMemoize).toEqualTypeOf< + typeof weakMapMemoize + >(weakMapMemoize) + + expectTypeOf(structuredAppSelector.memoize).toEqualTypeOf< + typeof weakMapMemoize + >(weakMapMemoize) + + expectTypeOf(structuredAppSelector.clearCache).returns.toBeVoid() + + expectTypeOf(structuredAppSelector.clearCache).parameters.toEqualTypeOf< + [] + >() + + expectTypeOf(structuredAppSelector.dependencies).items.toBeFunction() + + expectTypeOf(structuredAppSelector.dependencyRecomputations).toEqualTypeOf< + () => number + >() + + expectTypeOf(structuredAppSelector.recomputations).toEqualTypeOf< + () => number + >() + + expectTypeOf( + structuredAppSelector.resetDependencyRecomputations + ).toEqualTypeOf<() => void>() + + expectTypeOf(structuredAppSelector.resetRecomputations).toEqualTypeOf< + () => void + >() + + expectTypeOf( + structuredAppSelector.lastResult + ).returns.toEqualTypeOf(rootState) + + expectTypeOf( + structuredAppSelector.memoizedResultFunc + ).parameters.toEqualTypeOf<[Todo[], Alert[]]>([ + rootState.todos, + rootState.alerts + ]) + + expectTypeOf( + structuredAppSelector.memoizedResultFunc + ).returns.toEqualTypeOf< + ReturnType + >(structuredAppSelector.lastResult()) + + expectTypeOf(structuredAppSelector.memoizedResultFunc).toHaveProperty( + 'clearCache' + ) + + expectTypeOf(structuredAppSelector.resultFunc).returns.toEqualTypeOf< + ReturnType + >(structuredAppSelector.lastResult()) + }) + + test('StructuredSelectorCreator should lock down the state type', () => { + const createStructuredAppSelector: StructuredSelectorCreator = + createStructuredSelector + + const structuredAppSelector = createStructuredAppSelector( + { + todos: state => { + expectTypeOf(state).toEqualTypeOf(rootState) + + return state.todos + }, + alerts: state => { + expectTypeOf(state).toEqualTypeOf(rootState) + + return state.alerts + } + }, + createSelector.withTypes() + ) + + const { todos, alerts } = structuredAppSelector(rootState) + + expectTypeOf(todos).toEqualTypeOf() + + expectTypeOf(alerts).toEqualTypeOf() + + expectTypeOf(structuredAppSelector.argsMemoize).toEqualTypeOf< + typeof weakMapMemoize + >(weakMapMemoize) + + expectTypeOf(structuredAppSelector.memoize).toEqualTypeOf< + typeof weakMapMemoize + >(weakMapMemoize) + + expectTypeOf(structuredAppSelector.clearCache).returns.toBeVoid() + + expectTypeOf(structuredAppSelector.clearCache).parameters.toEqualTypeOf< + [] + >() + + expectTypeOf(structuredAppSelector.dependencies).items.toBeFunction() + + expectTypeOf(structuredAppSelector.dependencyRecomputations).toEqualTypeOf< + () => number + >() + + expectTypeOf(structuredAppSelector.recomputations).toEqualTypeOf< + () => number + >() + + expectTypeOf( + structuredAppSelector.resetDependencyRecomputations + ).toEqualTypeOf<() => void>() + + expectTypeOf(structuredAppSelector.resetRecomputations).toEqualTypeOf< + () => void + >() + + expectTypeOf( + structuredAppSelector.lastResult + ).returns.toEqualTypeOf(rootState) + + expectTypeOf( + structuredAppSelector.memoizedResultFunc + ).parameters.toEqualTypeOf<[Todo[], Alert[]]>([ + rootState.todos, + rootState.alerts + ]) + + expectTypeOf( + structuredAppSelector.memoizedResultFunc + ).returns.toEqualTypeOf< + ReturnType + >(structuredAppSelector.lastResult()) + + expectTypeOf(structuredAppSelector.memoizedResultFunc).toHaveProperty( + 'clearCache' + ) + + expectTypeOf(structuredAppSelector.resultFunc).returns.toEqualTypeOf< + ReturnType + >(structuredAppSelector.lastResult()) + }) }) From e7f39caba1af5fb28c9f1a2a17fb5e285b972086 Mon Sep 17 00:00:00 2001 From: Arya Emami Date: Wed, 3 Jan 2024 19:29:38 -0600 Subject: [PATCH 06/20] Change `SelectorsObject` from interface with index signature to `Record` type --- src/createStructuredSelector.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/createStructuredSelector.ts b/src/createStructuredSelector.ts index b71c188c6..b0d101413 100644 --- a/src/createStructuredSelector.ts +++ b/src/createStructuredSelector.ts @@ -207,9 +207,10 @@ export type TypedStructuredSelectorCreator = * * @public */ -export interface SelectorsObject { - [key: string]: Selector -} +export type SelectorsObject = Record< + string, + Selector +> /** * It provides a way to create structured selectors. From c0f7c8a2063de076f11cf813dd95634bec0615b1 Mon Sep 17 00:00:00 2001 From: Arya Emami Date: Wed, 3 Jan 2024 19:33:23 -0600 Subject: [PATCH 07/20] Change `createStructuredSelector.withTypes` type to arrow function - This was mainly done because `@typescript-eslint/eslint-plugin` has a rule called `@typescript-eslint/unbound-method`, which results to a lint error. --- src/createStructuredSelector.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/createStructuredSelector.ts b/src/createStructuredSelector.ts index b0d101413..69fb0ac48 100644 --- a/src/createStructuredSelector.ts +++ b/src/createStructuredSelector.ts @@ -345,9 +345,9 @@ export interface StructuredSelectorCreator { > & InterruptRecursion - withTypes< + withTypes: < OverrideStateType extends StateType - >(): StructuredSelectorCreator + >() => StructuredSelectorCreator } /** * A convenience function that simplifies returning an object From 68a119bfec1b695dbd90f49c0741b10edb8f2851 Mon Sep 17 00:00:00 2001 From: Arya Emami Date: Wed, 3 Jan 2024 19:39:16 -0600 Subject: [PATCH 08/20] Change `createSelector.withTypes` type to arrow function - This was mainly done because `@typescript-eslint/eslint-plugin` has a rule called `@typescript-eslint/unbound-method`, which results to a lint error. --- src/createSelectorCreator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/createSelectorCreator.ts b/src/createSelectorCreator.ts index aed72dd34..ac2238fac 100644 --- a/src/createSelectorCreator.ts +++ b/src/createSelectorCreator.ts @@ -176,7 +176,7 @@ export interface CreateSelectorFunction< * * @since 5.0.2 */ - withTypes(): CreateSelectorFunction< + withTypes: () => CreateSelectorFunction< MemoizeFunction, ArgsMemoizeFunction, OverrideStateType From 37ebaf896c1bf0d70fa1f466175a16c2371fb701 Mon Sep 17 00:00:00 2001 From: Arya Emami Date: Wed, 3 Jan 2024 20:01:54 -0600 Subject: [PATCH 09/20] Add `createStructuredSelector.withTypes` example for docs --- .../createStructuredSelector/withTypes.ts | 18 +++++ ...eateStructuredSelector.withTypes.test-d.ts | 4 ++ website/docs/api/createSelectorCreator.mdx | 2 +- website/docs/api/createStructuredSelector.mdx | 65 ++++++++++++++++++- 4 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 docs/examples/createStructuredSelector/withTypes.ts diff --git a/docs/examples/createStructuredSelector/withTypes.ts b/docs/examples/createStructuredSelector/withTypes.ts new file mode 100644 index 000000000..d0b083120 --- /dev/null +++ b/docs/examples/createStructuredSelector/withTypes.ts @@ -0,0 +1,18 @@ +import { createStructuredSelector } from 'reselect' + +export interface RootState { + todos: { id: number; completed: boolean }[] + alerts: { id: number; read: boolean }[] +} + +export const createStructuredAppSelector = + createStructuredSelector.withTypes() + +const structuredAppSelector = createStructuredAppSelector({ + // Type of `state` is set to `RootState`, no need to manually set the type + // highlight-start + todos: state => state.todos, + // highlight-end + alerts: state => state.alerts, + todoById: (state, id: number) => state.todos[id] +}) diff --git a/type-tests/createStructuredSelector.withTypes.test-d.ts b/type-tests/createStructuredSelector.withTypes.test-d.ts index a3ba802d9..17586bbfe 100644 --- a/type-tests/createStructuredSelector.withTypes.test-d.ts +++ b/type-tests/createStructuredSelector.withTypes.test-d.ts @@ -44,6 +44,10 @@ describe('createStructuredSelector.withTypes()', () => { createStructuredSelector.withTypes() test('locks down state type and infers types correctly', () => { + expectTypeOf(createStructuredSelector.withTypes).returns.toEqualTypeOf( + createStructuredSelector + ) + const structuredAppSelector = createStructuredAppSelector({ todos: state => { expectTypeOf(state).toEqualTypeOf(rootState) diff --git a/website/docs/api/createSelectorCreator.mdx b/website/docs/api/createSelectorCreator.mdx index 6f5886b2c..65908b1e9 100644 --- a/website/docs/api/createSelectorCreator.mdx +++ b/website/docs/api/createSelectorCreator.mdx @@ -17,7 +17,7 @@ Accepts either a `memoize` function and `...memoizeOptions` rest parameter, or s | Name | Description | | :----------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `options` | An options object containing the `memoize` function responsible for memoizing the `resultFunc` inside (e.g., `lruMemoize` or `weakMapMemoize`). It also provides additional options for customizing memoization. While the `memoize` property is mandatory, the rest are optional. | -| `options.argsMemoize?` | The optional memoize function that is used to memoize the arguments passed into the generated by (e.g., `lruMemoize` or `weakMapMemoize`).
**`Default`** = `lruMemoize` before 5.0.0 and `weakMapMemoize` after | +| `options.argsMemoize?` | The optional memoize function that is used to memoize the arguments passed into the generated by (e.g., `lruMemoize` or `weakMapMemoize`).
**`Default`** = `lruMemoize` before 5.0.0 and `weakMapMemoize` after | | `options.argsMemoizeOptions?` | Optional configuration options for the `argsMemoize` function. These options are passed to the `argsMemoize` function as the second argument.
since 5.0.0 | | `options.inputStabilityCheck?` | Overrides the global input stability check for the selector. Possible values are:
`once` - Run only the first time the selector is called.
`always` - Run every time the selector is called.
`never` - Never run the input stability check.
**`Default`** = `'once'`
since 5.0.0 | | `options.memoize` | The memoize function that is used to memoize the `resultFunc` inside (e.g., `lruMemoize` or `weakMapMemoize`). since 5.0.0 | diff --git a/website/docs/api/createStructuredSelector.mdx b/website/docs/api/createStructuredSelector.mdx index d12b1e096..4a8c521a3 100644 --- a/website/docs/api/createStructuredSelector.mdx +++ b/website/docs/api/createStructuredSelector.mdx @@ -248,7 +248,7 @@ const nestedSelector = createStructuredSelector({ A helper type that allows you to create a pre-typed version of tailored to the provided root state type. - +{/* START: createStructuredSelector/createStructuredAppSelector.ts */} - +{/* END: createStructuredSelector/createStructuredAppSelector.ts */} + +## Defining a Pre-Typed `createSelector` + +As of Reselect 5.0.2, you can create a "pre-typed" version of where the `state` type is predefined. This allows you to set the `state` type once, eliminating the need to specify it with every call. + +To do this, you can call `CreateStructuredSelector.withTypes()`: + +{/* START: createStructuredSelector/withTypes.ts */} + + + + +```ts title="createStructuredSelector/withTypes.ts" +import { createStructuredSelector } from 'reselect' + +export interface RootState { + todos: { id: number; completed: boolean }[] + alerts: { id: number; read: boolean }[] +} + +export const createStructuredAppSelector = + createStructuredSelector.withTypes() + +const structuredAppSelector = createStructuredAppSelector({ + // Type of `state` is set to `RootState`, no need to manually set the type + // highlight-start + todos: state => state.todos, + // highlight-end + alerts: state => state.alerts, + todoById: (state, id: number) => state.todos[id] +}) +``` + + + + +```js title="createStructuredSelector/withTypes.js" +import { createStructuredSelector } from 'reselect' + +export const createStructuredAppSelector = createStructuredSelector.withTypes() + +const structuredAppSelector = createStructuredAppSelector({ + // Type of `state` is set to `RootState`, no need to manually set the type + // highlight-start + todos: state => state.todos, + // highlight-end + alerts: state => state.alerts, + todoById: (state, id) => state.todos[id] +}) +``` + + + + +{/* END: createStructuredSelector/withTypes.ts */} From 986ca8a438b5c2596825540cfc4b029947337fc3 Mon Sep 17 00:00:00 2001 From: Arya Emami Date: Wed, 3 Jan 2024 20:27:14 -0600 Subject: [PATCH 10/20] Add JSDocs for `StateType` generic type parameter in `StructuredSelectorCreator` --- src/createStructuredSelector.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/createStructuredSelector.ts b/src/createStructuredSelector.ts index 69fb0ac48..6245f435b 100644 --- a/src/createStructuredSelector.ts +++ b/src/createStructuredSelector.ts @@ -217,6 +217,8 @@ export type SelectorsObject = Record< * The structured selector can take multiple input selectors * and map their output to an object with specific keys. * + * @template StateType - The type of state that the structured selectors created with this structured selector creator will operate on. + * * @see {@link https://reselect.js.org/api/createStructuredSelector `createStructuredSelector`} * * @public From 121fc3609f370b8127ca178bb6720f55a48fc651 Mon Sep 17 00:00:00 2001 From: Arya Emami Date: Wed, 3 Jan 2024 20:28:06 -0600 Subject: [PATCH 11/20] Add JSDocs for `StateType` generic type parameter in `SelectorsObject` --- src/createStructuredSelector.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/createStructuredSelector.ts b/src/createStructuredSelector.ts index 6245f435b..115ecb855 100644 --- a/src/createStructuredSelector.ts +++ b/src/createStructuredSelector.ts @@ -205,6 +205,8 @@ export type TypedStructuredSelectorCreator = /** * Represents an object where each property is a selector function. * + * @template StateType - The type of state that all the selectors operate on. + * * @public */ export type SelectorsObject = Record< From 25544d78e0dabe189d287b671728bb5256b701bb Mon Sep 17 00:00:00 2001 From: Arya Emami Date: Wed, 3 Jan 2024 20:28:34 -0600 Subject: [PATCH 12/20] Add JSDocs for `createStructuredSelector.withTypes` --- src/createStructuredSelector.ts | 42 +++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/createStructuredSelector.ts b/src/createStructuredSelector.ts index 115ecb855..42f75e283 100644 --- a/src/createStructuredSelector.ts +++ b/src/createStructuredSelector.ts @@ -349,14 +349,56 @@ export interface StructuredSelectorCreator { > & InterruptRecursion + /** + * Creates a "pre-typed" version of + * {@linkcode createStructuredSelector createStructuredSelector} + * where the `state` type is predefined. + * + * This allows you to set the `state` type once, eliminating the need to + * specify it with every + * {@linkcode createStructuredSelector createStructuredSelector} call. + * + * @returns A pre-typed `createStructuredSelector` with the state type already defined. + * + * @example + * ```ts + * import { createStructuredSelector } from 'reselect' + * + * export interface RootState { + * todos: { id: number; completed: boolean }[] + * alerts: { id: number; read: boolean }[] + * } + * + * export const createStructuredAppSelector = + * createStructuredSelector.withTypes() + * + * const structuredAppSelector = createStructuredAppSelector({ + * // Type of `state` is set to `RootState`, no need to manually set the type + * todos: state => state.todos, + * alerts: state => state.alerts, + * todoById: (state, id: number) => state.todos[id] + * }) + * + * ``` + * @template OverrideStateType - The specific type of state used by all structured selectors created with this structured selector creator. + * + * @see {@link https://reselect.js.org/api/createstructuredselector#defining-a-pre-typed-createstructuredselector `createSelector.withTypes`} + * + * @since 5.0.2 + */ withTypes: < OverrideStateType extends StateType >() => StructuredSelectorCreator } + /** * A convenience function that simplifies returning an object * made up of selector results. * + * @param inputSelectorsObject - A key value pair consisting of input selectors. + * @param selectorCreator - A custom selector creator function. It defaults to `createSelector`. + * @returns A memoized structured selector. + * * @example * Modern Use Case * ```ts From 8b93622768580429fddac6d94ea75e58c72d397d Mon Sep 17 00:00:00 2001 From: Arya Emami Date: Wed, 3 Jan 2024 20:28:58 -0600 Subject: [PATCH 13/20] Fix typos inside docs --- website/docs/api/createStructuredSelector.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/api/createStructuredSelector.mdx b/website/docs/api/createStructuredSelector.mdx index 4a8c521a3..042b876a1 100644 --- a/website/docs/api/createStructuredSelector.mdx +++ b/website/docs/api/createStructuredSelector.mdx @@ -303,11 +303,11 @@ const structuredSelector = createStructuredAppSelector({ {/* END: createStructuredSelector/createStructuredAppSelector.ts */} -## Defining a Pre-Typed `createSelector` +## Defining a Pre-Typed `createStructuredSelector` As of Reselect 5.0.2, you can create a "pre-typed" version of where the `state` type is predefined. This allows you to set the `state` type once, eliminating the need to specify it with every call. -To do this, you can call `CreateStructuredSelector.withTypes()`: +To do this, you can call `createStructuredSelector.withTypes()`: {/* START: createStructuredSelector/withTypes.ts */} From 4cc0883fd2ec2399b268f4e919ef57aa7d96894c Mon Sep 17 00:00:00 2001 From: Arya Emami Date: Thu, 4 Jan 2024 17:11:11 -0600 Subject: [PATCH 14/20] Deprecate `TypedStructuredSelectorCreator` --- src/createStructuredSelector.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/createStructuredSelector.ts b/src/createStructuredSelector.ts index 42f75e283..02359bb90 100644 --- a/src/createStructuredSelector.ts +++ b/src/createStructuredSelector.ts @@ -77,6 +77,7 @@ export type RootStateSelectors = { * * @since 5.0.0 * @public + * @deprecated Please use {@linkcode StructuredSelectorCreator.withTypes createstructuredselector.withTypes()} instead. */ export type TypedStructuredSelectorCreator = /** From 3e39fccce5d17072609da4dc8845cd6dad9b0868 Mon Sep 17 00:00:00 2001 From: Arya Emami Date: Wed, 3 Jan 2024 20:28:58 -0600 Subject: [PATCH 15/20] Fix typos inside docs --- src/createStructuredSelector.ts | 1 + website/docs/api/createStructuredSelector.mdx | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/createStructuredSelector.ts b/src/createStructuredSelector.ts index 42f75e283..6e01167b4 100644 --- a/src/createStructuredSelector.ts +++ b/src/createStructuredSelector.ts @@ -77,6 +77,7 @@ export type RootStateSelectors = { * * @since 5.0.0 * @public + * @deprecated Please use {@linkcode StructuredSelectorCreator.withTypes createStructuredSelector.withTypes()} instead. */ export type TypedStructuredSelectorCreator = /** diff --git a/website/docs/api/createStructuredSelector.mdx b/website/docs/api/createStructuredSelector.mdx index 4a8c521a3..042b876a1 100644 --- a/website/docs/api/createStructuredSelector.mdx +++ b/website/docs/api/createStructuredSelector.mdx @@ -303,11 +303,11 @@ const structuredSelector = createStructuredAppSelector({ {/* END: createStructuredSelector/createStructuredAppSelector.ts */} -## Defining a Pre-Typed `createSelector` +## Defining a Pre-Typed `createStructuredSelector` As of Reselect 5.0.2, you can create a "pre-typed" version of where the `state` type is predefined. This allows you to set the `state` type once, eliminating the need to specify it with every call. -To do this, you can call `CreateStructuredSelector.withTypes()`: +To do this, you can call `createStructuredSelector.withTypes()`: {/* START: createStructuredSelector/withTypes.ts */} From 9b4b7acaf1ca0703e66410f198642e50d76bfd4a Mon Sep 17 00:00:00 2001 From: Arya Emami Date: Thu, 4 Jan 2024 19:12:25 -0600 Subject: [PATCH 16/20] Add todo comments to remove certain test blocks - Added todo comments to remove certain test blocks after removal of `TypedStructuredSelectorCreator`. --- src/createStructuredSelector.ts | 2 +- type-tests/createStructuredSelector.test-d.ts | 3 +++ ...eateStructuredSelector.withTypes.test-d.ts | 1 + typescript_test/test.ts | 25 ++++--------------- 4 files changed, 10 insertions(+), 21 deletions(-) diff --git a/src/createStructuredSelector.ts b/src/createStructuredSelector.ts index 2f8535f20..794f311c9 100644 --- a/src/createStructuredSelector.ts +++ b/src/createStructuredSelector.ts @@ -41,11 +41,11 @@ export type RootStateSelectors = { } /** + * @deprecated Please use {@linkcode StructuredSelectorCreator.withTypes createStructuredSelector.withTypes()} instead. This type will be removed in the future. * @template RootState - The type of the root state object. * * @since 5.0.0 * @public - * @deprecated Please use {@linkcode StructuredSelectorCreator.withTypes createStructuredSelector.withTypes()} instead. This type will be removed in the future. */ export type TypedStructuredSelectorCreator = /** diff --git a/type-tests/createStructuredSelector.test-d.ts b/type-tests/createStructuredSelector.test-d.ts index 99833a8f2..864cb44f2 100644 --- a/type-tests/createStructuredSelector.test-d.ts +++ b/type-tests/createStructuredSelector.test-d.ts @@ -35,6 +35,8 @@ const rootState: RootState = { } describe('createStructuredSelector', () => { + + // TODO: Remove this test block once `TypedStructuredSelectorCreator` is removed. test('TypedStructuredSelectorCreator should lock down state type', () => { const createStructuredAppSelector: TypedStructuredSelectorCreator = createStructuredSelector @@ -112,6 +114,7 @@ describe('createStructuredSelector', () => { >(structuredSelector.lastResult()) }) + // TODO: Remove this test block once `TypedStructuredSelectorCreator` is removed. test('TypedStructuredSelectorCreator should correctly infer memoize and argsMemoize', () => { const createSelectorLru = createSelectorCreator({ memoize: lruMemoize, diff --git a/type-tests/createStructuredSelector.withTypes.test-d.ts b/type-tests/createStructuredSelector.withTypes.test-d.ts index 17586bbfe..9bb5b1ff7 100644 --- a/type-tests/createStructuredSelector.withTypes.test-d.ts +++ b/type-tests/createStructuredSelector.withTypes.test-d.ts @@ -294,6 +294,7 @@ describe('createStructuredSelector.withTypes()', () => { >(structuredAppSelector.lastResult()) }) + // TODO: Remove this test block once `TypedStructuredSelectorCreator` is removed. test('should work alongside TypedStructuredSelectorCreator', () => { const createStructuredAppSelector: TypedStructuredSelectorCreator = createStructuredSelector.withTypes() diff --git a/typescript_test/test.ts b/typescript_test/test.ts index c58547228..0795f2e70 100644 --- a/typescript_test/test.ts +++ b/typescript_test/test.ts @@ -17,8 +17,8 @@ import { createSelector, createSelectorCreator, createStructuredSelector, - referenceEqualityCheck, - lruMemoize + lruMemoize, + referenceEqualityCheck } from 'reselect' import { expectExactType } from './typesTestUtils' @@ -748,8 +748,8 @@ function testCreateStructuredSelector() { bar: number } - const typedStructuredSelectorCreator: TypedStructuredSelectorCreator = - createStructuredSelector + const typedStructuredSelectorCreator = + createStructuredSelector.withTypes() const selector = typedStructuredSelectorCreator({ foo: state => state.foo, @@ -772,12 +772,10 @@ function testCreateStructuredSelector() { }) typedStructuredSelectorCreator({ - // @ts-expect-error bar: state => state.foo }) typedStructuredSelectorCreator({ - // @ts-expect-error baz: state => state.foo }) @@ -820,6 +818,7 @@ function testCreateStructuredSelector() { selectorGenerics({ bar: '42' }) } +// TODO: Remove this function once `TypedStructuredSelectorCreator` is removed. function testTypedCreateStructuredSelector() { type RootState = { foo: string @@ -921,20 +920,6 @@ function testStructuredSelectorTypeParams() { // bar: selectBar, // ^^^ because this is missing, an error is thrown }) - - const typedStructuredSelectorCreator: TypedStructuredSelectorCreator = - createStructuredSelector - - // This works - typedStructuredSelectorCreator({ - foo: selectFoo, - bar: selectBar - }) - - // // So does this - // typedStructuredSelectorCreator>({ - // foo: selectFoo - // }) } function multiArgMemoize any>( From 73e45f7870dc504d7bd6e17a7b505030a005ad70 Mon Sep 17 00:00:00 2001 From: Arya Emami Date: Thu, 4 Jan 2024 19:14:09 -0600 Subject: [PATCH 17/20] Remove `TypedStructuredSelectorCreator` from `README` --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index c0f9b973b..877066feb 100644 --- a/README.md +++ b/README.md @@ -149,7 +149,6 @@ Version 5.0.0 introduces several new features and improvements: - **Selector API Enhancements**: - Removed the second overload of `createStructuredSelector` due to its susceptibility to runtime errors. - - Added the `TypedStructuredSelectorCreator` utility type (_currently a work-in-progress_) to facilitate the creation of a pre-typed version of `createStructuredSelector` for your root state. - **Additional Functionalities**: From 140f38f0707fe2db2ac40ca1e0daa07a6ce3dc29 Mon Sep 17 00:00:00 2001 From: Arya Emami Date: Thu, 4 Jan 2024 19:21:21 -0600 Subject: [PATCH 18/20] Remove `createStructuredAppSelector.ts` from examples --- .../createStructuredAppSelector.ts | 21 ------------------- 1 file changed, 21 deletions(-) delete mode 100644 docs/examples/createStructuredSelector/createStructuredAppSelector.ts diff --git a/docs/examples/createStructuredSelector/createStructuredAppSelector.ts b/docs/examples/createStructuredSelector/createStructuredAppSelector.ts deleted file mode 100644 index ae17e1564..000000000 --- a/docs/examples/createStructuredSelector/createStructuredAppSelector.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type { TypedStructuredSelectorCreator } from 'reselect' -import { createStructuredSelector } from 'reselect' - -interface RootState { - todos: { - id: number - completed: boolean - title: string - description: string - }[] - alerts: { id: number; read: boolean }[] -} - -export const createStructuredAppSelector: TypedStructuredSelectorCreator = - createStructuredSelector - -const structuredSelector = createStructuredAppSelector({ - // The `state` argument is correctly typed as `RootState` - todos: state => state.todos, - alerts: state => state.alerts -}) From 025c1a491d2c3fc94ae4b0468cc85eb023b4e568 Mon Sep 17 00:00:00 2001 From: Arya Emami Date: Thu, 4 Jan 2024 19:21:55 -0600 Subject: [PATCH 19/20] Remove `TypedStructuredSelectorCreator` from docs --- website/docs/api/createStructuredSelector.mdx | 59 ------------------- website/docs/introduction/v5-summary.mdx | 1 - website/src/components/InternalLinks.tsx | 8 --- 3 files changed, 68 deletions(-) diff --git a/website/docs/api/createStructuredSelector.mdx b/website/docs/api/createStructuredSelector.mdx index 042b876a1..bf0faea8a 100644 --- a/website/docs/api/createStructuredSelector.mdx +++ b/website/docs/api/createStructuredSelector.mdx @@ -244,65 +244,6 @@ const nestedSelector = createStructuredSelector({ }) ``` -## `TypedStructuredSelectorCreator` (since 5.0.0) - -A helper type that allows you to create a pre-typed version of tailored to the provided root state type. - -{/* START: createStructuredSelector/createStructuredAppSelector.ts */} - - - - -```ts title="createStructuredSelector/createStructuredAppSelector.ts" -import type { TypedStructuredSelectorCreator } from 'reselect' -import { createStructuredSelector } from 'reselect' - -interface RootState { - todos: { - id: number - completed: boolean - title: string - description: string - }[] - alerts: { id: number; read: boolean }[] -} - -export const createStructuredAppSelector: TypedStructuredSelectorCreator = - createStructuredSelector - -const structuredSelector = createStructuredAppSelector({ - // The `state` argument is correctly typed as `RootState` - todos: state => state.todos, - alerts: state => state.alerts -}) -``` - - - - -```js title="createStructuredSelector/createStructuredAppSelector.js" -import { createStructuredSelector } from 'reselect' - -export const createStructuredAppSelector = createStructuredSelector - -const structuredSelector = createStructuredAppSelector({ - // The `state` argument is correctly typed as `RootState` - todos: state => state.todos, - alerts: state => state.alerts -}) -``` - - - - -{/* END: createStructuredSelector/createStructuredAppSelector.ts */} - ## Defining a Pre-Typed `createStructuredSelector` As of Reselect 5.0.2, you can create a "pre-typed" version of where the `state` type is predefined. This allows you to set the `state` type once, eliminating the need to specify it with every call. diff --git a/website/docs/introduction/v5-summary.mdx b/website/docs/introduction/v5-summary.mdx index 28bbf7c3a..9651885fe 100644 --- a/website/docs/introduction/v5-summary.mdx +++ b/website/docs/introduction/v5-summary.mdx @@ -31,7 +31,6 @@ Version 5.0.0 introduces several new features and improvements: ## Selector API Enhancements - Removed the second overload of due to its susceptibility to runtime errors. -- Added the utility type to facilitate the creation of a pre-typed version of for your root state. ## Additional Functionalities diff --git a/website/src/components/InternalLinks.tsx b/website/src/components/InternalLinks.tsx index 462778df2..4c30b2427 100644 --- a/website/src/components/InternalLinks.tsx +++ b/website/src/components/InternalLinks.tsx @@ -89,13 +89,5 @@ export const InternalLinks = { createStructuredSelector - )), - TypedStructuredSelectorCreator: memo(() => ( - - TypedStructuredSelectorCreator - )) } as const satisfies Record> From 136897066ad0c7dfa2915e65ec00a352adfca4c9 Mon Sep 17 00:00:00 2001 From: Arya Emami Date: Fri, 5 Jan 2024 03:55:12 -0600 Subject: [PATCH 20/20] Change version to 5.0.2 to workaround CI issue --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2c41eda8e..baa9394cf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "reselect", - "version": "5.0.1", + "version": "5.0.2", "description": "Selectors for Redux.", "main": "./dist/cjs/reselect.cjs", "module": "./dist/reselect.legacy-esm.js",