Socket
Socket
Sign inDemoInstall

reselect

Package Overview
Dependencies
Maintainers
6
Versions
53
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

reselect - npm Package Compare versions

Comparing version 5.0.1 to 5.1.0

292

dist/reselect.d.ts

@@ -203,3 +203,3 @@ /**

*/
type SelectorArray = readonly Selector[];
type SelectorArray<State = any> = readonly Selector<State>[];
/**

@@ -782,6 +782,7 @@ * Extracts an array of all return types from all input selectors.

* @template ArgsMemoizeFunction - The type of the optional memoize function that is used to memoize the arguments passed into the output selector generated by `createSelector` (e.g., `lruMemoize` or `weakMapMemoize`). If none is explicitly provided, `weakMapMemoize` will be used.
* @template StateType - The type of state that the selectors created with this selector creator will operate on.
*
* @public
*/
interface CreateSelectorFunction<MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize, ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize> {
interface CreateSelectorFunction<MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize, ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize, StateType = any> {
/**

@@ -798,5 +799,5 @@ * Creates a memoized selector function.

*
* @see {@link https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc-createselectoroptions createSelector}
* @see {@link https://reselect.js.org/api/createselector `createSelector`}
*/
<InputSelectors extends SelectorArray, Result>(...createSelectorArgs: [
<InputSelectors extends SelectorArray<StateType>, Result>(...createSelectorArgs: [
...inputSelectors: InputSelectors,

@@ -816,5 +817,5 @@ combiner: Combiner<InputSelectors, Result>

*
* @see {@link https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc-createselectoroptions createSelector}
* @see {@link https://reselect.js.org/api/createselector `createSelector`}
*/
<InputSelectors extends SelectorArray, Result, OverrideMemoizeFunction extends UnknownMemoizer = MemoizeFunction, OverrideArgsMemoizeFunction extends UnknownMemoizer = ArgsMemoizeFunction>(...createSelectorArgs: [
<InputSelectors extends SelectorArray<StateType>, Result, OverrideMemoizeFunction extends UnknownMemoizer = MemoizeFunction, OverrideArgsMemoizeFunction extends UnknownMemoizer = ArgsMemoizeFunction>(...createSelectorArgs: [
...inputSelectors: InputSelectors,

@@ -837,5 +838,40 @@ combiner: Combiner<InputSelectors, Result>,

*
* @see {@link https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc-createselectoroptions createSelector}
* @see {@link https://reselect.js.org/api/createselector `createSelector`}
*/
<InputSelectors extends SelectorArray, Result, OverrideMemoizeFunction extends UnknownMemoizer = MemoizeFunction, OverrideArgsMemoizeFunction extends UnknownMemoizer = ArgsMemoizeFunction>(inputSelectors: [...InputSelectors], combiner: Combiner<InputSelectors, Result>, createSelectorOptions?: Simplify<CreateSelectorOptions<MemoizeFunction, ArgsMemoizeFunction, OverrideMemoizeFunction, OverrideArgsMemoizeFunction>>): OutputSelector<InputSelectors, Result, OverrideMemoizeFunction, OverrideArgsMemoizeFunction> & InterruptRecursion;
<InputSelectors extends SelectorArray<StateType>, Result, OverrideMemoizeFunction extends UnknownMemoizer = MemoizeFunction, OverrideArgsMemoizeFunction extends UnknownMemoizer = ArgsMemoizeFunction>(inputSelectors: [...InputSelectors], combiner: Combiner<InputSelectors, Result>, createSelectorOptions?: Simplify<CreateSelectorOptions<MemoizeFunction, ArgsMemoizeFunction, OverrideMemoizeFunction, OverrideArgsMemoizeFunction>>): OutputSelector<InputSelectors, Result, OverrideMemoizeFunction, OverrideArgsMemoizeFunction> & InterruptRecursion;
/**
* Creates a "pre-typed" version of {@linkcode createSelector createSelector}
* where the `state` type is predefined.
*
* This allows you to set the `state` type once, eliminating the need to
* specify it with every {@linkcode createSelector createSelector} call.
*
* @returns A pre-typed `createSelector` with the state type already defined.
*
* @example
* ```ts
* import { createSelector } from 'reselect'
*
* export interface RootState {
* todos: { id: number; completed: boolean }[]
* alerts: { id: number; read: boolean }[]
* }
*
* export const createAppSelector = createSelector.withTypes<RootState>()
*
* const selectTodoIds = createAppSelector(
* [
* // Type of `state` is set to `RootState`, no need to manually set the type
* state => state.todos
* ],
* todos => todos.map(({ id }) => id)
* )
* ```
* @template OverrideStateType - The specific type of state used by all selectors created with this selector creator.
*
* @see {@link https://reselect.js.org/api/createselector#defining-a-pre-typed-createselector `createSelector.withTypes`}
*
* @since 5.1.0
*/
withTypes: <OverrideStateType extends StateType>() => CreateSelectorFunction<MemoizeFunction, ArgsMemoizeFunction, OverrideStateType>;
}

@@ -915,30 +951,153 @@ /**

*/
declare const createSelector: CreateSelectorFunction<typeof weakMapMemoize, typeof weakMapMemoize>;
declare const createSelector: CreateSelectorFunction<typeof weakMapMemoize, typeof weakMapMemoize, any>;
/**
* Represents a mapping of selectors to their return types.
*
* @WIP
* @template TObject - An object type where each property is a selector function.
*
* @public
*/
type SelectorsMap<T extends SelectorsObject> = {
[Key in keyof T]: ReturnType<T[Key]>;
type SelectorResultsMap<TObject extends SelectorsObject> = {
[Key in keyof TObject]: ReturnType<TObject[Key]>;
};
/**
* Allows you to create a pre-typed version of {@linkcode createStructuredSelector createStructuredSelector}
* For your root state.
* Represents a mapping of selectors for each key in a given root state.
*
* This type is a utility that takes a root state object type and
* generates a corresponding set of selectors. Each selector is associated
* with a key in the root state, allowing for the selection
* of specific parts of the state.
*
* @template RootState - The type of the root state object.
*
* @since 5.0.0
* @public
* @WIP
*/
interface TypedStructuredSelectorCreator<RootState = any> {
<InputSelectorsObject extends {
[Key in keyof RootState]: Selector<RootState, RootState[Key], []>;
} = {
[Key in keyof RootState]: Selector<RootState, RootState[Key], []>;
}, MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize, ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize>(selectors: InputSelectorsObject, selectorCreator?: CreateSelectorFunction<MemoizeFunction, ArgsMemoizeFunction>): OutputSelector<ObjectValuesToTuple<InputSelectorsObject>, SelectorsMap<InputSelectorsObject>, MemoizeFunction, ArgsMemoizeFunction>;
}
interface SelectorsObject {
[key: string]: Selector;
}
type RootStateSelectors<RootState = any> = {
[Key in keyof RootState]: Selector<RootState, RootState[Key], []>;
};
/**
* @deprecated Please use {@linkcode StructuredSelectorCreator.withTypes createStructuredSelector.withTypes<RootState>()} instead. This type will be removed in the future.
* @template RootState - The type of the root state object.
*
* @since 5.0.0
* @public
*/
type TypedStructuredSelectorCreator<RootState = any> =
/**
* 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
* <caption>Modern Use Case</caption>
* ```ts
* import { createSelector, createStructuredSelector } from 'reselect'
*
* interface RootState {
* todos: {
* id: number
* completed: boolean
* title: string
* description: string
* }[]
* alerts: { id: number; read: boolean }[]
* }
*
* // This:
* const structuredSelector = createStructuredSelector(
* {
* todos: (state: RootState) => state.todos,
* alerts: (state: RootState) => state.alerts,
* todoById: (state: RootState, id: number) => state.todos[id]
* },
* createSelector
* )
*
* // Is essentially the same as this:
* const selector = createSelector(
* [
* (state: RootState) => state.todos,
* (state: RootState) => state.alerts,
* (state: RootState, id: number) => state.todos[id]
* ],
* (todos, alerts, todoById) => {
* return {
* todos,
* alerts,
* todoById
* }
* }
* )
* ```
*
* @example
* <caption>In your component:</caption>
* ```tsx
* import type { RootState } from 'createStructuredSelector/modernUseCase'
* import { structuredSelector } from 'createStructuredSelector/modernUseCase'
* import type { FC } from 'react'
* import { useSelector } from 'react-redux'
*
* interface Props {
* id: number
* }
*
* const MyComponent: FC<Props> = ({ id }) => {
* const { todos, alerts, todoById } = useSelector((state: RootState) =>
* structuredSelector(state, id)
* )
*
* return (
* <div>
* Next to do is:
* <h2>{todoById.title}</h2>
* <p>Description: {todoById.description}</p>
* <ul>
* <h3>All other to dos:</h3>
* {todos.map(todo => (
* <li key={todo.id}>{todo.title}</li>
* ))}
* </ul>
* </div>
* )
* }
* ```
*
* @example
* <caption>Simple Use Case</caption>
* ```ts
* const selectA = state => state.a
* const selectB = state => state.b
*
* // The result function in the following selector
* // is simply building an object from the input selectors
* const structuredSelector = createSelector(selectA, selectB, (a, b) => ({
* a,
* b
* }))
*
* const result = structuredSelector({ a: 1, b: 2 }) // will produce { x: 1, y: 2 }
* ```
*
* @template InputSelectorsObject - The shape of the input selectors object.
* @template MemoizeFunction - The type of the memoize function that is used to create the structured selector. It defaults to `weakMapMemoize`.
* @template ArgsMemoizeFunction - The type of the of the memoize function that is used to memoize the arguments passed into the generated structured selector. It defaults to `weakMapMemoize`.
*
* @see {@link https://reselect.js.org/api/createStructuredSelector `createStructuredSelector`}
*/
<InputSelectorsObject extends RootStateSelectors<RootState> = RootStateSelectors<RootState>, MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize, ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize>(inputSelectorsObject: InputSelectorsObject, selectorCreator?: CreateSelectorFunction<MemoizeFunction, ArgsMemoizeFunction>) => OutputSelector<ObjectValuesToTuple<InputSelectorsObject>, Simplify<SelectorResultsMap<InputSelectorsObject>>, MemoizeFunction, ArgsMemoizeFunction> & InterruptRecursion;
/**
* Represents an object where each property is a selector function.
*
* @template StateType - The type of state that all the selectors operate on.
*
* @public
*/
type SelectorsObject<StateType = any> = Record<string, Selector<StateType>>;
/**
* It provides a way to create structured selectors.

@@ -948,2 +1107,4 @@ * The structured selector can take multiple input selectors

*
* @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`}

@@ -953,3 +1114,3 @@ *

*/
interface StructuredSelectorCreator {
interface StructuredSelectorCreator<StateType = any> {
/**

@@ -1006,2 +1167,35 @@ * A convenience function that simplifies returning an object

* @example
* <caption>In your component:</caption>
* ```tsx
* import type { RootState } from 'createStructuredSelector/modernUseCase'
* import { structuredSelector } from 'createStructuredSelector/modernUseCase'
* import type { FC } from 'react'
* import { useSelector } from 'react-redux'
*
* interface Props {
* id: number
* }
*
* const MyComponent: FC<Props> = ({ id }) => {
* const { todos, alerts, todoById } = useSelector((state: RootState) =>
* structuredSelector(state, id)
* )
*
* return (
* <div>
* Next to do is:
* <h2>{todoById.title}</h2>
* <p>Description: {todoById.description}</p>
* <ul>
* <h3>All other to dos:</h3>
* {todos.map(todo => (
* <li key={todo.id}>{todo.title}</li>
* ))}
* </ul>
* </div>
* )
* }
* ```
*
* @example
* <caption>Simple Use Case</caption>

@@ -1028,3 +1222,41 @@ * ```ts

*/
<InputSelectorsObject extends SelectorsObject, MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize, ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize>(inputSelectorsObject: InputSelectorsObject, selectorCreator?: CreateSelectorFunction<MemoizeFunction, ArgsMemoizeFunction>): OutputSelector<ObjectValuesToTuple<InputSelectorsObject>, Simplify<SelectorsMap<InputSelectorsObject>>, MemoizeFunction, ArgsMemoizeFunction> & InterruptRecursion;
<InputSelectorsObject extends SelectorsObject<StateType>, MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize, ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize>(inputSelectorsObject: InputSelectorsObject, selectorCreator?: CreateSelectorFunction<MemoizeFunction, ArgsMemoizeFunction>): OutputSelector<ObjectValuesToTuple<InputSelectorsObject>, Simplify<SelectorResultsMap<InputSelectorsObject>>, MemoizeFunction, ArgsMemoizeFunction> & 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<RootState>()
*
* 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.1.0
*/
withTypes: <OverrideStateType extends StateType>() => StructuredSelectorCreator<OverrideStateType>;
}

@@ -1035,2 +1267,6 @@ /**

*
* @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

@@ -1204,2 +1440,2 @@ * <caption>Modern Use Case</caption>

export { Combiner, CreateSelectorFunction, CreateSelectorOptions, DefaultMemoizeFields, DevModeCheckFrequency, DevModeChecks, DevModeChecksExecutionInfo, EqualityFn, ExtractMemoizerFields, GetParamsFromSelectors, GetStateFromSelectors, LruMemoizeOptions, MemoizeOptionsFromParameters, OutputSelector, OutputSelectorFields, OverrideMemoizeOptions, Selector, SelectorArray, SelectorResultArray, StructuredSelectorCreator, TypedStructuredSelectorCreator, UnknownMemoizer, WeakMapMemoizeOptions, createSelector, createSelectorCreator, createStructuredSelector, lruMemoize, referenceEqualityCheck, setGlobalDevModeChecks, autotrackMemoize as unstable_autotrackMemoize, weakMapMemoize };
export { Combiner, CreateSelectorFunction, CreateSelectorOptions, DefaultMemoizeFields, DevModeCheckFrequency, DevModeChecks, DevModeChecksExecutionInfo, EqualityFn, ExtractMemoizerFields, GetParamsFromSelectors, GetStateFromSelectors, LruMemoizeOptions, MemoizeOptionsFromParameters, OutputSelector, OutputSelectorFields, OverrideMemoizeOptions, RootStateSelectors, Selector, SelectorArray, SelectorResultArray, SelectorResultsMap, SelectorsObject, StructuredSelectorCreator, TypedStructuredSelectorCreator, UnknownMemoizer, WeakMapMemoizeOptions, createSelector, createSelectorCreator, createStructuredSelector, lruMemoize, referenceEqualityCheck, setGlobalDevModeChecks, autotrackMemoize as unstable_autotrackMemoize, weakMapMemoize };

90

dist/reselect.legacy-esm.js

@@ -23,22 +23,24 @@ var __defProp = Object.defineProperty;

// src/devModeChecks/identityFunctionCheck.ts
var runIdentityFunctionCheck = (resultFunc) => {
let isInputSameAsOutput = false;
try {
const emptyObject = {};
if (resultFunc(emptyObject) === emptyObject)
isInputSameAsOutput = true;
} catch (e) {
}
if (isInputSameAsOutput) {
let stack = void 0;
var runIdentityFunctionCheck = (resultFunc, inputSelectorsResults, outputSelectorResult) => {
if (inputSelectorsResults.length === 1 && inputSelectorsResults[0] === outputSelectorResult) {
let isInputSameAsOutput = false;
try {
throw new Error();
const emptyObject = {};
if (resultFunc(emptyObject) === emptyObject)
isInputSameAsOutput = true;
} catch (e) {
;
({ stack } = e);
}
console.warn(
"The result function returned its own inputs without modification. e.g\n`createSelector([state => state.todos], todos => todos)`\nThis could lead to inefficient memoization and unnecessary re-renders.\nEnsure transformation logic is in the result function, and extraction logic is in the input selectors.",
{ stack }
);
if (isInputSameAsOutput) {
let stack = void 0;
try {
throw new Error();
} catch (e) {
;
({ stack } = e);
}
console.warn(
"The result function returned its own inputs without modification. e.g\n`createSelector([state => state.todos], todos => todos)`\nThis could lead to inefficient memoization and unnecessary re-renders.\nEnsure transformation logic is in the result function, and extraction logic is in the input selectors.",
{ stack }
);
}
}

@@ -566,3 +568,3 @@ };

function memoized() {
var _a;
var _a, _b;
let cacheNode = fnNode;

@@ -608,3 +610,3 @@ const { length } = arguments;

if (resultEqualityCheck) {
const lastResultValue = (_a = lastResult == null ? void 0 : lastResult.deref()) != null ? _a : lastResult;
const lastResultValue = (_b = (_a = lastResult == null ? void 0 : lastResult.deref) == null ? void 0 : _a.call(lastResult)) != null ? _b : lastResult;
if (lastResultValue != null && resultEqualityCheck(lastResultValue, result)) {

@@ -676,2 +678,3 @@ result = lastResultValue;

);
lastResult = memoizedResultFunc.apply(null, inputSelectorResults);
if (process.env.NODE_ENV !== "production") {

@@ -681,3 +684,5 @@ const { identityFunctionCheck, inputStabilityCheck } = getDevModeChecksExecutionInfo(firstRun, devModeChecks);

identityFunctionCheck.run(
resultFunc
resultFunc,
inputSelectorResults,
lastResult
);

@@ -699,3 +704,2 @@ }

}
lastResult = memoizedResultFunc.apply(null, inputSelectorResults);
return lastResult;

@@ -720,2 +724,5 @@ }, ...finalArgsMemoizeOptions);

};
Object.assign(createSelector2, {
withTypes: () => createSelector2
});
return createSelector2;

@@ -726,20 +733,25 @@ }

// src/createStructuredSelector.ts
var createStructuredSelector = (inputSelectorsObject, selectorCreator = createSelector) => {
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) => {
return inputSelectorResults.reduce((composition, value, index) => {
composition[inputSelectorKeys[index]] = value;
return composition;
}, {});
}
);
return structuredSelector;
};
var createStructuredSelector = Object.assign(
(inputSelectorsObject, selectorCreator = createSelector) => {
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) => {
return inputSelectorResults.reduce((composition, value, index) => {
composition[inputSelectorKeys[index]] = value;
return composition;
}, {});
}
);
return structuredSelector;
},
{ withTypes: () => createStructuredSelector }
);
export {

@@ -746,0 +758,0 @@ createSelector,

{
"name": "reselect",
"version": "5.0.1",
"version": "5.1.0",
"description": "Selectors for Redux.",

@@ -34,4 +34,4 @@ "main": "./dist/cjs/reselect.cjs",

"test:cov": "vitest run --coverage",
"type-check": "vitest --run typecheck",
"type-check:trace": "vitest --run typecheck && tsc --noEmit -p typescript_test/tsconfig.json --generateTrace trace && npx @typescript/analyze-trace trace && rimraf trace",
"type-check": "vitest --run --typecheck",
"type-check:trace": "vitest --run --typecheck && tsc --noEmit -p typescript_test/tsconfig.json --generateTrace trace && npx @typescript/analyze-trace trace && rimraf trace",
"test:typescript": "tsc --noEmit -p typescript_test/tsconfig.json",

@@ -59,3 +59,3 @@ "docs:start": "yarn --cwd website start",

"devDependencies": {
"@reduxjs/toolkit": "^2.0.0-rc.1",
"@reduxjs/toolkit": "^2.0.1",
"@testing-library/react": "^14.1.2",

@@ -82,3 +82,3 @@ "@types/lodash": "^4.14.175",

"react-dom": "^18.2.0",
"react-redux": "^9.0.0-rc.0",
"react-redux": "^9.0.4",
"rimraf": "^3.0.2",

@@ -88,4 +88,4 @@ "shelljs": "^0.8.5",

"typescript": "5.2",
"vitest": "^0.34"
"vitest": "^1.1.1"
}
}

@@ -152,3 +152,2 @@ # Reselect

- 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.

@@ -155,0 +154,0 @@ - **Additional Functionalities**:

@@ -0,0 +0,0 @@ // Original autotracking implementation source:

@@ -0,0 +0,0 @@ import { createNode, updateNode } from './proxy'

@@ -0,0 +0,0 @@ // Original source:

@@ -0,0 +0,0 @@ import type { Cell } from './autotracking'

@@ -0,0 +0,0 @@ export function assert(

@@ -32,2 +32,3 @@ import { weakMapMemoize } from './weakMapMemoize'

* @template ArgsMemoizeFunction - The type of the optional memoize function that is used to memoize the arguments passed into the output selector generated by `createSelector` (e.g., `lruMemoize` or `weakMapMemoize`). If none is explicitly provided, `weakMapMemoize` will be used.
* @template StateType - The type of state that the selectors created with this selector creator will operate on.
*

@@ -38,3 +39,4 @@ * @public

MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize,
ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize
ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize,
StateType = any
> {

@@ -52,5 +54,5 @@ /**

*
* @see {@link https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc-createselectoroptions createSelector}
* @see {@link https://reselect.js.org/api/createselector `createSelector`}
*/
<InputSelectors extends SelectorArray, Result>(
<InputSelectors extends SelectorArray<StateType>, Result>(
...createSelectorArgs: [

@@ -79,6 +81,6 @@ ...inputSelectors: InputSelectors,

*
* @see {@link https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc-createselectoroptions createSelector}
* @see {@link https://reselect.js.org/api/createselector `createSelector`}
*/
<
InputSelectors extends SelectorArray,
InputSelectors extends SelectorArray<StateType>,
Result,

@@ -121,6 +123,6 @@ OverrideMemoizeFunction extends UnknownMemoizer = MemoizeFunction,

*
* @see {@link https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc-createselectoroptions createSelector}
* @see {@link https://reselect.js.org/api/createselector `createSelector`}
*/
<
InputSelectors extends SelectorArray,
InputSelectors extends SelectorArray<StateType>,
Result,

@@ -147,2 +149,42 @@ OverrideMemoizeFunction extends UnknownMemoizer = MemoizeFunction,

InterruptRecursion
/**
* Creates a "pre-typed" version of {@linkcode createSelector createSelector}
* where the `state` type is predefined.
*
* This allows you to set the `state` type once, eliminating the need to
* specify it with every {@linkcode createSelector createSelector} call.
*
* @returns A pre-typed `createSelector` with the state type already defined.
*
* @example
* ```ts
* import { createSelector } from 'reselect'
*
* export interface RootState {
* todos: { id: number; completed: boolean }[]
* alerts: { id: number; read: boolean }[]
* }
*
* export const createAppSelector = createSelector.withTypes<RootState>()
*
* const selectTodoIds = createAppSelector(
* [
* // Type of `state` is set to `RootState`, no need to manually set the type
* state => state.todos
* ],
* todos => todos.map(({ id }) => id)
* )
* ```
* @template OverrideStateType - The specific type of state used by all selectors created with this selector creator.
*
* @see {@link https://reselect.js.org/api/createselector#defining-a-pre-typed-createselector `createSelector.withTypes`}
*
* @since 5.1.0
*/
withTypes: <OverrideStateType extends StateType>() => CreateSelectorFunction<
MemoizeFunction,
ArgsMemoizeFunction,
OverrideStateType
>
}

@@ -235,3 +277,4 @@

/**
* Creates a selector creator function with the specified memoization function and options for customizing memoization behavior.
* Creates a selector creator function with the specified memoization
* function and options for customizing memoization behavior.
*

@@ -374,2 +417,6 @@ * @param memoizeOrOptions - Either A `memoize` function or an `options` object containing the `memoize` function.

// apply arguments instead of spreading for performance.
// @ts-ignore
lastResult = memoizedResultFunc.apply(null, inputSelectorResults)
if (process.env.NODE_ENV !== 'production') {

@@ -380,3 +427,5 @@ const { identityFunctionCheck, inputStabilityCheck } =

identityFunctionCheck.run(
resultFunc as Combiner<InputSelectors, Result>
resultFunc as Combiner<InputSelectors, Result>,
inputSelectorResults,
lastResult
)

@@ -402,6 +451,2 @@ }

// apply arguments instead of spreading for performance.
// @ts-ignore
lastResult = memoizedResultFunc.apply(null, inputSelectorResults)
return lastResult

@@ -437,2 +482,7 @@ }, ...finalArgsMemoizeOptions) as unknown as Selector<

}
Object.assign(createSelector, {
withTypes: () => createSelector
})
return createSelector as CreateSelectorFunction<

@@ -439,0 +489,0 @@ MemoizeFunction,

@@ -16,29 +16,148 @@ import { createSelector } from './createSelectorCreator'

/**
* Represents a mapping of selectors to their return types.
*
* @WIP
* @template TObject - An object type where each property is a selector function.
*
* @public
*/
type SelectorsMap<T extends SelectorsObject> = {
[Key in keyof T]: ReturnType<T[Key]>
export type SelectorResultsMap<TObject extends SelectorsObject> = {
[Key in keyof TObject]: ReturnType<TObject[Key]>
}
// TODO: Write more type tests for `TypedStructuredSelectorCreator`.
/**
* Allows you to create a pre-typed version of {@linkcode createStructuredSelector createStructuredSelector}
* For your root state.
* Represents a mapping of selectors for each key in a given root state.
*
* This type is a utility that takes a root state object type and
* generates a corresponding set of selectors. Each selector is associated
* with a key in the root state, allowing for the selection
* of specific parts of the state.
*
* @template RootState - The type of the root state object.
*
* @since 5.0.0
* @public
* @WIP
*/
export interface TypedStructuredSelectorCreator<RootState = any> {
export type RootStateSelectors<RootState = any> = {
[Key in keyof RootState]: Selector<RootState, RootState[Key], []>
}
/**
* @deprecated Please use {@linkcode StructuredSelectorCreator.withTypes createStructuredSelector.withTypes<RootState>()} instead. This type will be removed in the future.
* @template RootState - The type of the root state object.
*
* @since 5.0.0
* @public
*/
export type TypedStructuredSelectorCreator<RootState = any> =
/**
* 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
* <caption>Modern Use Case</caption>
* ```ts
* import { createSelector, createStructuredSelector } from 'reselect'
*
* interface RootState {
* todos: {
* id: number
* completed: boolean
* title: string
* description: string
* }[]
* alerts: { id: number; read: boolean }[]
* }
*
* // This:
* const structuredSelector = createStructuredSelector(
* {
* todos: (state: RootState) => state.todos,
* alerts: (state: RootState) => state.alerts,
* todoById: (state: RootState, id: number) => state.todos[id]
* },
* createSelector
* )
*
* // Is essentially the same as this:
* const selector = createSelector(
* [
* (state: RootState) => state.todos,
* (state: RootState) => state.alerts,
* (state: RootState, id: number) => state.todos[id]
* ],
* (todos, alerts, todoById) => {
* return {
* todos,
* alerts,
* todoById
* }
* }
* )
* ```
*
* @example
* <caption>In your component:</caption>
* ```tsx
* import type { RootState } from 'createStructuredSelector/modernUseCase'
* import { structuredSelector } from 'createStructuredSelector/modernUseCase'
* import type { FC } from 'react'
* import { useSelector } from 'react-redux'
*
* interface Props {
* id: number
* }
*
* const MyComponent: FC<Props> = ({ id }) => {
* const { todos, alerts, todoById } = useSelector((state: RootState) =>
* structuredSelector(state, id)
* )
*
* return (
* <div>
* Next to do is:
* <h2>{todoById.title}</h2>
* <p>Description: {todoById.description}</p>
* <ul>
* <h3>All other to dos:</h3>
* {todos.map(todo => (
* <li key={todo.id}>{todo.title}</li>
* ))}
* </ul>
* </div>
* )
* }
* ```
*
* @example
* <caption>Simple Use Case</caption>
* ```ts
* const selectA = state => state.a
* const selectB = state => state.b
*
* // The result function in the following selector
* // is simply building an object from the input selectors
* const structuredSelector = createSelector(selectA, selectB, (a, b) => ({
* a,
* b
* }))
*
* const result = structuredSelector({ a: 1, b: 2 }) // will produce { x: 1, y: 2 }
* ```
*
* @template InputSelectorsObject - The shape of the input selectors object.
* @template MemoizeFunction - The type of the memoize function that is used to create the structured selector. It defaults to `weakMapMemoize`.
* @template ArgsMemoizeFunction - The type of the of the memoize function that is used to memoize the arguments passed into the generated structured selector. It defaults to `weakMapMemoize`.
*
* @see {@link https://reselect.js.org/api/createStructuredSelector `createStructuredSelector`}
*/
<
InputSelectorsObject extends {
[Key in keyof RootState]: Selector<RootState, RootState[Key], []>
} = {
[Key in keyof RootState]: Selector<RootState, RootState[Key], []>
},
InputSelectorsObject extends RootStateSelectors<RootState> = RootStateSelectors<RootState>,
MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize,
ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize
>(
selectors: InputSelectorsObject,
inputSelectorsObject: InputSelectorsObject,
selectorCreator?: CreateSelectorFunction<

@@ -48,13 +167,21 @@ MemoizeFunction,

>
): OutputSelector<
) => OutputSelector<
ObjectValuesToTuple<InputSelectorsObject>,
SelectorsMap<InputSelectorsObject>,
Simplify<SelectorResultsMap<InputSelectorsObject>>,
MemoizeFunction,
ArgsMemoizeFunction
>
}
> &
InterruptRecursion
interface SelectorsObject {
[key: string]: Selector
}
/**
* 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<StateType = any> = Record<
string,
Selector<StateType>
>

@@ -66,2 +193,4 @@ /**

*
* @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`}

@@ -71,3 +200,3 @@ *

*/
export interface StructuredSelectorCreator {
export interface StructuredSelectorCreator<StateType = any> {
/**

@@ -124,2 +253,35 @@ * A convenience function that simplifies returning an object

* @example
* <caption>In your component:</caption>
* ```tsx
* import type { RootState } from 'createStructuredSelector/modernUseCase'
* import { structuredSelector } from 'createStructuredSelector/modernUseCase'
* import type { FC } from 'react'
* import { useSelector } from 'react-redux'
*
* interface Props {
* id: number
* }
*
* const MyComponent: FC<Props> = ({ id }) => {
* const { todos, alerts, todoById } = useSelector((state: RootState) =>
* structuredSelector(state, id)
* )
*
* return (
* <div>
* Next to do is:
* <h2>{todoById.title}</h2>
* <p>Description: {todoById.description}</p>
* <ul>
* <h3>All other to dos:</h3>
* {todos.map(todo => (
* <li key={todo.id}>{todo.title}</li>
* ))}
* </ul>
* </div>
* )
* }
* ```
*
* @example
* <caption>Simple Use Case</caption>

@@ -147,3 +309,3 @@ * ```ts

<
InputSelectorsObject extends SelectorsObject,
InputSelectorsObject extends SelectorsObject<StateType>,
MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize,

@@ -159,3 +321,3 @@ ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize

ObjectValuesToTuple<InputSelectorsObject>,
Simplify<SelectorsMap<InputSelectorsObject>>,
Simplify<SelectorResultsMap<InputSelectorsObject>>,
MemoizeFunction,

@@ -165,2 +327,43 @@ ArgsMemoizeFunction

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<RootState>()
*
* 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.1.0
*/
withTypes: <
OverrideStateType extends StateType
>() => StructuredSelectorCreator<OverrideStateType>
}

@@ -172,2 +375,6 @@

*
* @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

@@ -219,33 +426,39 @@ * <caption>Modern Use Case</caption>

*/
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

@@ -12,2 +12,4 @@ import type { AnyFunction } from '../types'

* @param resultFunc - The result function to be checked.
* @param inputSelectorsResults - The results of the input selectors.
* @param outputSelectorResult - The result of the output selector.
*

@@ -19,26 +21,35 @@ * @see {@link https://reselect.js.org/api/development-only-stability-checks#identityfunctioncheck `identityFunctionCheck`}

*/
export const runIdentityFunctionCheck = (resultFunc: AnyFunction) => {
let isInputSameAsOutput = false
try {
const emptyObject = {}
if (resultFunc(emptyObject) === emptyObject) isInputSameAsOutput = true
} catch {
// Do nothing
}
if (isInputSameAsOutput) {
let stack: string | undefined = undefined
export const runIdentityFunctionCheck = (
resultFunc: AnyFunction,
inputSelectorsResults: unknown[],
outputSelectorResult: unknown
) => {
if (
inputSelectorsResults.length === 1 &&
inputSelectorsResults[0] === outputSelectorResult
) {
let isInputSameAsOutput = false
try {
throw new Error()
} catch (e) {
// eslint-disable-next-line @typescript-eslint/no-extra-semi, no-extra-semi
;({ stack } = e as Error)
const emptyObject = {}
if (resultFunc(emptyObject) === emptyObject) isInputSameAsOutput = true
} catch {
// Do nothing
}
console.warn(
'The result function returned its own inputs without modification. e.g' +
'\n`createSelector([state => state.todos], todos => todos)`' +
'\nThis could lead to inefficient memoization and unnecessary re-renders.' +
'\nEnsure transformation logic is in the result function, and extraction logic is in the input selectors.',
{ stack }
)
if (isInputSameAsOutput) {
let stack: string | undefined = undefined
try {
throw new Error()
} catch (e) {
// eslint-disable-next-line @typescript-eslint/no-extra-semi, no-extra-semi
;({ stack } = e as Error)
}
console.warn(
'The result function returned its own inputs without modification. e.g' +
'\n`createSelector([state => state.todos], todos => todos)`' +
'\nThis could lead to inefficient memoization and unnecessary re-renders.' +
'\nEnsure transformation logic is in the result function, and extraction logic is in the input selectors.',
{ stack }
)
}
}
}

@@ -0,0 +0,0 @@ import type { CreateSelectorOptions, UnknownMemoizer } from '../types'

@@ -0,0 +0,0 @@ import type { DevModeChecks } from '../types'

@@ -6,2 +6,5 @@ export { autotrackMemoize as unstable_autotrackMemoize } from './autotrackMemoize/autotrackMemoize'

export type {
RootStateSelectors,
SelectorResultsMap,
SelectorsObject,
StructuredSelectorCreator,

@@ -8,0 +11,0 @@ TypedStructuredSelectorCreator

@@ -0,0 +0,0 @@ import type {

@@ -44,3 +44,3 @@ import type { MergeParameters } from './versionedTypes'

*/
export type SelectorArray = readonly Selector[]
export type SelectorArray<State = any> = readonly Selector<State>[]

@@ -47,0 +47,0 @@ /**

@@ -0,0 +0,0 @@ import { runIdentityFunctionCheck } from './devModeChecks/identityFunctionCheck'

export type { MergeParameters } from './ts47-mergeParameters'

@@ -0,0 +0,0 @@ // This entire implementation courtesy of Anders Hjelsberg:

@@ -235,3 +235,3 @@ // Original source:

if (resultEqualityCheck) {
const lastResultValue = lastResult?.deref() ?? lastResult
const lastResultValue = lastResult?.deref?.() ?? lastResult
if (

@@ -238,0 +238,0 @@ lastResultValue != null &&

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc