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.0-beta.1 to 5.0.0-rc.0

src/devModeChecks/identityFunctionCheck.ts

831

dist/reselect.d.ts
/**
* @public
*/
declare const defaultEqualityCheck: EqualityFn;
/**
* @public
*/
interface DefaultMemoizeOptions {
/**
* Used to compare the individual arguments of the provided calculation function.
*
* @default defaultEqualityCheck
*/
equalityCheck?: EqualityFn;
/**
* If provided, used to compare a newly generated output value against previous values in the cache.
* If a match is found, the old value is returned. This addresses the common
* ```ts
* todos.map(todo => todo.id)
* ```
* use case, where an update to another field in the original data causes a recalculation
* due to changed references, but the output is still effectively the same.
*/
resultEqualityCheck?: EqualityFn;
/**
* The cache size for the selector. If greater than 1, the selector will use an LRU cache internally.
*
* @default 1
*/
maxSize?: number;
}
/**
* The standard memoize function used by `createSelector`.
* @param func - The function to be memoized.
* @param equalityCheckOrOptions - Either an equality check function or an options object.
* @returns A memoized function with a `.clearCache()` method attached.
* Represents the longest array within an array of arrays.
*
* @template Func - The type of the function that is memoized.
* @template ArrayOfTuples An array of arrays.
*
* @see {@link https://github.com/reduxjs/reselect#defaultmemoizefunc-equalitycheckoroptions--defaultequalitycheck defaultMemoize}
*
* @public
*/
declare function defaultMemoize<Func extends AnyFunction>(func: Func, equalityCheckOrOptions?: EqualityFn | DefaultMemoizeOptions): Func & {
clearCache: () => void;
};
/**
* @internal
*/
type LongestTuple<T extends readonly unknown[][]> = T extends [
infer U extends unknown[]
] ? U : T extends [infer U, ...infer R extends unknown[][]] ? MostProperties<U, LongestTuple<R>> : never;
type LongestTuple<ArrayOfTuples extends readonly unknown[][]> = ArrayOfTuples extends [infer FirstArray extends unknown[]] ? FirstArray : ArrayOfTuples extends [
infer FirstArray,
...infer RestArrays extends unknown[][]
] ? LongerOfTwo<FirstArray, LongestTuple<RestArrays>> : never;
/**
* Determines the longer of two array types.
*
* @template ArrayOne First array type.
* @template ArrayTwo Second array type.
*
* @internal
*/
type MostProperties<T, U> = keyof U extends keyof T ? T : U;
type LongerOfTwo<ArrayOne, ArrayTwo> = keyof ArrayTwo extends keyof ArrayOne ? ArrayOne : ArrayTwo;
/**
* Extracts the element at a specific index in an array.
*
* @template ArrayType The array type.
* @template Index The index type.
*
* @internal
*/
type ElementAt<T extends unknown[], N extends keyof any> = N extends keyof T ? T[N] : unknown;
type ElementAt<ArrayType extends unknown[], Index extends PropertyKey> = Index extends keyof ArrayType ? ArrayType[Index] : unknown;
/**
* Maps each array in an array of arrays to its element at a given index.
*
* @template ArrayOfTuples An array of arrays.
* @template Index The index to extract from each array.
*
* @internal
*/
type ElementsAt<T extends readonly unknown[][], N extends keyof any> = {
[K in keyof T]: ElementAt<T[K], N>;
type ElementsAtGivenIndex<ArrayOfTuples extends readonly unknown[][], Index extends PropertyKey> = {
[ArrayIndex in keyof ArrayOfTuples]: ElementAt<ArrayOfTuples[ArrayIndex], Index>;
};
/**
* Computes the intersection of all types in a tuple.
*
* @template Tuple A tuple of types.
*
* @internal
*/
type Intersect<T extends readonly unknown[]> = T extends [] ? unknown : T extends [infer H, ...infer T] ? H & Intersect<T> : T[number];
type Intersect<Tuple extends readonly unknown[]> = Tuple extends [] ? unknown : Tuple extends [infer Head, ...infer Tail] ? Head & Intersect<Tail> : Tuple[number];
/**
* Merges a tuple of arrays into a single tuple, intersecting types at each index.
*
* @template ArrayOfTuples An array of tuples.
* @template LongestArray The longest array in ArrayOfTuples.
*
* @internal
*/
type MergeTuples<T extends readonly unknown[][], L extends unknown[] = LongestTuple<T>> = {
[K in keyof L]: Intersect<ElementsAt<T, K>>;
type MergeTuples<ArrayOfTuples extends readonly unknown[][], LongestArray extends unknown[] = LongestTuple<ArrayOfTuples>> = {
[Index in keyof LongestArray]: Intersect<ElementsAtGivenIndex<ArrayOfTuples, Index>>;
};
/**
* Extracts the parameter types from a tuple of functions.
*
* @template FunctionsArray An array of function types.
*
* @internal
*/
type ExtractParameters<T extends readonly AnyFunction[]> = {
[K in keyof T]: Parameters<T[K]>;
type ExtractParameters<FunctionsArray extends readonly AnyFunction[]> = {
[Index in keyof FunctionsArray]: Parameters<FunctionsArray[Index]>;
};
/**
* Merges the parameters of a tuple of functions into a single tuple.
*
* @template FunctionsArray An array of function types.
*
* @internal
*/
type MergeParameters<T extends readonly AnyFunction[]> = '0' extends keyof T ? MergeTuples<ExtractParameters<T>> : Parameters<T[number]>;
type MergeParameters<FunctionsArray extends readonly AnyFunction[]> = '0' extends keyof FunctionsArray ? MergeTuples<ExtractParameters<FunctionsArray>> : Parameters<FunctionsArray[number]>;
/**
* @public
*/
interface WeakMapMemoizeOptions<T = any> {
/**
* If provided, used to compare a newly generated output value against previous values in the cache.
* If a match is found, the old value is returned. This addresses the common
* ```ts
* todos.map(todo => todo.id)
* ```
* use case, where an update to another field in the original data causes a recalculation
* due to changed references, but the output is still effectively the same.
*/
resultEqualityCheck?: EqualityFn<T>;
}
/**
* Creates a tree of `WeakMap`-based cache nodes based on the identity of the
* arguments it's been called with (in this case, the extracted values from your input selectors).
* This allows `weakMapMemoize` to have an effectively infinite cache size.
* Cache results will be kept in memory as long as references to the arguments still exist,
* and then cleared out as the arguments are garbage-collected.
*
* __Design Tradeoffs for `weakMapMemoize`:__
* - Pros:
* - It has an effectively infinite cache size, but you have no control over
* how long values are kept in cache as it's based on garbage collection and `WeakMap`s.
* - Cons:
* - There's currently no way to alter the argument comparisons.
* They're based on strict reference equality.
* - It's roughly the same speed as `defaultMemoize`, although likely a fraction slower.
*
* __Use Cases for `weakMapMemoize`:__
* - This memoizer is likely best used for cases where you need to call the
* same selector instance with many different arguments, such as a single
* selector instance that is used in a list item component and called with
* item IDs like:
* ```ts
* useSelector(state => selectSomeData(state, props.category))
* ```
* @param func - The function to be memoized.
* @returns A memoized function with a `.clearCache()` method attached.
*
* @example
* <caption>Using `createSelector`</caption>
* ```ts
* import { createSelector, weakMapMemoize } from 'reselect'
*
* interface RootState {
* items: { id: number; category: string; name: string }[]
* }
*
* const selectItemsByCategory = createSelector(
* [
* (state: RootState) => state.items,
* (state: RootState, category: string) => category
* ],
* (items, category) => items.filter(item => item.category === category),
* {
* memoize: weakMapMemoize,
* argsMemoize: weakMapMemoize
* }
* )
* ```
*
* @example
* <caption>Using `createSelectorCreator`</caption>
* ```ts
* import { createSelectorCreator, weakMapMemoize } from 'reselect'
*
* const createSelectorWeakMap = createSelectorCreator({ memoize: weakMapMemoize, argsMemoize: weakMapMemoize })
*
* const selectItemsByCategory = createSelectorWeakMap(
* [
* (state: RootState) => state.items,
* (state: RootState, category: string) => category
* ],
* (items, category) => items.filter(item => item.category === category)
* )
* ```
*
* @template Func - The type of the function that is memoized.
*
* @see {@link https://github.com/reduxjs/reselect#weakmapmemoizefunc---since-500 weakMapMemoize}
*
* @since 5.0.0
* @public
* @experimental
*/
declare function weakMapMemoize<Func extends AnyFunction>(func: Func, options?: WeakMapMemoizeOptions<ReturnType<Func>>): Func & {
clearCache: () => void;
resultsCount: () => number;
resetResultsCount: () => void;
};
/**
* A standard selector function.

@@ -122,24 +206,19 @@ * @template State - The first value, often a Redux root state object.

* @template MemoizeFunction - The type of the memoize function that is used to memoize the `resultFunc` inside `createSelector` (e.g., `defaultMemoize` or `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., `defaultMemoize` or `weakMapMemoize`). If none is explicitly provided, `defaultMemoize` will be used.
* @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., `defaultMemoize` or `weakMapMemoize`). If none is explicitly provided, `weakMapMemoize` will be used.
* @template OverrideMemoizeFunction - The type of the optional `memoize` function that could be passed into the options object inside `createSelector` to override the original `memoize` function that was initially passed into `createSelectorCreator`.
* @template OverrideArgsMemoizeFunction - The type of the optional `argsMemoize` function that could be passed into the options object inside `createSelector` to override the original `argsMemoize` function that was initially passed into `createSelectorCreator`. If none was initially provided, `defaultMemoize` will be used.
* @template OverrideArgsMemoizeFunction - The type of the optional `argsMemoize` function that could be passed into the options object inside `createSelector` to override the original `argsMemoize` function that was initially passed into `createSelectorCreator`. If none was initially provided, `weakMapMemoize` will be used.
*
* @public
*/
interface CreateSelectorOptions<MemoizeFunction extends UnknownMemoizer = typeof defaultMemoize, ArgsMemoizeFunction extends UnknownMemoizer = typeof defaultMemoize, OverrideMemoizeFunction extends UnknownMemoizer = never, OverrideArgsMemoizeFunction extends UnknownMemoizer = never> {
interface CreateSelectorOptions<MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize, ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize, OverrideMemoizeFunction extends UnknownMemoizer = never, OverrideArgsMemoizeFunction extends UnknownMemoizer = never> {
/**
* Overrides the global input stability check for the selector.
* - `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.
* Reselect performs additional checks in development mode to help identify
* and warn about potential issues in selector behavior. This option
* allows you to customize the behavior of these checks per selector.
*
* @default 'once'
* @see {@link https://github.com/reduxjs/reselect#debugging-tools debugging-tools}
*
* @see {@link https://github.com/reduxjs/reselect#development-only-checks development-only-checks}
* @see {@link https://github.com/reduxjs/reselect#inputstabilitycheck inputStabilityCheck}
* @see {@link https://github.com/reduxjs/reselect#per-selector-configuration per-selector-configuration}
*
* @since 5.0.0
*/
inputStabilityCheck?: StabilityCheckFrequency;
devModeChecks?: Partial<DevModeChecks>;
/**

@@ -155,8 +234,8 @@ * The memoize function that is used to memoize the {@linkcode OutputSelectorFields.resultFunc resultFunc}

*
* const selectTodoById = createSelector(
* const selectItemsByCategory = createSelector(
* [
* (state: RootState) => state.todos,
* (state: RootState, id: number) => id
* (state: RootState) => state.items,
* (state: RootState, category: string) => category
* ],
* (todos) => todos[id],
* (items, category) => items.filter(item => item.category === category),
* { memoize: weakMapMemoize }

@@ -168,7 +247,11 @@ * )

*/
memoize: FallbackIfNever<OverrideMemoizeFunction, MemoizeFunction>;
memoize?: FallbackIfNever<OverrideMemoizeFunction, MemoizeFunction>;
/**
* The optional memoize function that is used to memoize the arguments passed into the output selector generated by `createSelector` (e.g., `defaultMemoize` or `weakMapMemoize`).
* The optional memoize function that is used to memoize the arguments
* passed into the output selector generated by `createSelector`
* (e.g., `defaultMemoize` or `weakMapMemoize`).
*
* When passed directly into `createSelector`, it overrides the `argsMemoize` function initially passed into `createSelectorCreator`. If none was initially provided, `defaultMemoize` will be used.
* When passed directly into `createSelector`, it overrides the
* `argsMemoize` function initially passed into `createSelectorCreator`.
* If none was initially provided, `weakMapMemoize` will be used.
*

@@ -179,8 +262,8 @@ * @example

*
* const selectTodoById = createSelector(
* const selectItemsByCategory = createSelector(
* [
* (state: RootState) => state.todos,
* (state: RootState, id: number) => id
* (state: RootState) => state.items,
* (state: RootState, category: string) => category
* ],
* (todos) => todos[id],
* (items, category) => items.filter(item => item.category === category),
* { argsMemoize: weakMapMemoize }

@@ -190,3 +273,3 @@ * )

*
* @default defaultMemoize
* @default weakMapMemoize
*

@@ -225,19 +308,48 @@ * @since 5.0.0

* @template MemoizeFunction - The type of the memoize function that is used to memoize the `resultFunc` inside `createSelector` (e.g., `defaultMemoize` or `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., `defaultMemoize` or `weakMapMemoize`). If none is explicitly provided, `defaultMemoize` will be used.
* @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., `defaultMemoize` or `weakMapMemoize`). If none is explicitly provided, `weakMapMemoize` will be used.
*
* @public
*/
type OutputSelectorFields<InputSelectors extends SelectorArray = SelectorArray, Result = unknown, MemoizeFunction extends UnknownMemoizer = typeof defaultMemoize, ArgsMemoizeFunction extends UnknownMemoizer = typeof defaultMemoize> = {
/** The final function passed to `createSelector`. Otherwise known as the `combiner`.*/
type OutputSelectorFields<InputSelectors extends SelectorArray = SelectorArray, Result = unknown, MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize, ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize> = {
/**
* The final function passed to `createSelector`. Otherwise known as the `combiner`.
*/
resultFunc: Combiner<InputSelectors, Result>;
/** The memoized version of {@linkcode OutputSelectorFields.resultFunc resultFunc}. */
/**
* The memoized version of {@linkcode OutputSelectorFields.resultFunc resultFunc}.
*/
memoizedResultFunc: Combiner<InputSelectors, Result> & ExtractMemoizerFields<MemoizeFunction>;
/** Returns the last result calculated by the output selector. */
/**
* @Returns The last result calculated by {@linkcode OutputSelectorFields.memoizedResultFunc memoizedResultFunc}.
*/
lastResult: () => Result;
/** An array of the input selectors. */
/**
* The array of the input selectors used by `createSelector` to compose the
* combiner ({@linkcode OutputSelectorFields.memoizedResultFunc memoizedResultFunc}).
*/
dependencies: InputSelectors;
/** Counts the number of times the output has been recalculated. */
/**
* Counts the number of times {@linkcode OutputSelectorFields.memoizedResultFunc memoizedResultFunc} has been recalculated.
*/
recomputations: () => number;
/** Resets the count of `recomputations` count to 0. */
resetRecomputations: () => 0;
/**
* Resets the count of {@linkcode OutputSelectorFields.recomputations recomputations} count to 0.
*/
resetRecomputations: () => void;
/**
* Counts the number of times the input selectors ({@linkcode OutputSelectorFields.dependencies dependencies})
* have been recalculated. This is distinct from {@linkcode OutputSelectorFields.recomputations recomputations},
* which tracks the recalculations of the result function.
*
* @since 5.0.0
*/
dependencyRecomputations: () => number;
/**
* Resets the count {@linkcode OutputSelectorFields.dependencyRecomputations dependencyRecomputations}
* for the input selectors ({@linkcode OutputSelectorFields.dependencies dependencies})
* of a memoized selector.
*
* @since 5.0.0
*/
resetDependencyRecomputations: () => void;
} & Simplify<Required<Pick<CreateSelectorOptions<MemoizeFunction, ArgsMemoizeFunction>, 'argsMemoize' | 'memoize'>>>;

@@ -250,7 +362,7 @@ /**

* @template MemoizeFunction - The type of the memoize function that is used to memoize the `resultFunc` inside `createSelector` (e.g., `defaultMemoize` or `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., `defaultMemoize` or `weakMapMemoize`). If none is explicitly provided, `defaultMemoize` will be used.
* @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., `defaultMemoize` or `weakMapMemoize`). If none is explicitly provided, `weakMapMemoize` will be used.
*
* @public
*/
type OutputSelector<InputSelectors extends SelectorArray = SelectorArray, Result = unknown, MemoizeFunction extends UnknownMemoizer = typeof defaultMemoize, ArgsMemoizeFunction extends UnknownMemoizer = typeof defaultMemoize> = Selector<GetStateFromSelectors<InputSelectors>, Result, GetParamsFromSelectors<InputSelectors>> & ExtractMemoizerFields<ArgsMemoizeFunction> & OutputSelectorFields<InputSelectors, Result, MemoizeFunction, ArgsMemoizeFunction>;
type OutputSelector<InputSelectors extends SelectorArray = SelectorArray, Result = unknown, MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize, ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize> = Selector<GetStateFromSelectors<InputSelectors>, Result, GetParamsFromSelectors<InputSelectors>> & ExtractMemoizerFields<ArgsMemoizeFunction> & OutputSelectorFields<InputSelectors, Result, MemoizeFunction, ArgsMemoizeFunction>;
/**

@@ -273,30 +385,70 @@ * A function that takes input selectors' return values as arguments and returns a result. Otherwise known as `resultFunc`.

/**
* A selector that is assumed to have one additional argument, such as
* the props from a React component.
* A standard function returning true if two values are considered equal.
*
* @public
*/
type ParametricSelector<State, Props, Result> = Selector<State, Result, [
Props,
...any
]>;
type EqualityFn<T = any> = (a: T, b: T) => boolean;
/**
* A generated selector that is assumed to have one additional argument.
* The frequency of development mode checks.
*
* @since 5.0.0
* @public
*/
type OutputParametricSelector<State, Props, Result> = ParametricSelector<State, Props, Result> & OutputSelectorFields<SelectorArray, Result>;
type DevModeCheckFrequency = 'always' | 'once' | 'never';
/**
* A standard function returning true if two values are considered equal.
* Represents the configuration for development mode checks.
*
* @since 5.0.0
* @public
*/
type EqualityFn = (a: any, b: any) => boolean;
interface DevModeChecks {
/**
* Overrides the global input stability check for the selector.
* - `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'
*
* @see {@link https://github.com/reduxjs/reselect#debugging-tools debugging-tools}
* @see {@link https://github.com/reduxjs/reselect#inputstabilitycheck inputStabilityCheck}
* @see {@link https://github.com/reduxjs/reselect#2-per-selector-by-passing-an-inputstabilitycheck-option-directly-to-createselector per-selector-configuration}
*
* @since 5.0.0
*/
inputStabilityCheck: DevModeCheckFrequency;
/**
* Overrides the global identity function check for the selector.
* - `once` - Run only the first time the selector is called.
* - `always` - Run every time the selector is called.
* - `never` - Never run the identity function check.
*
* @default 'once'
*
* @see {@link https://github.com/reduxjs/reselect#debugging-tools debugging-tools}
* @see {@link https://github.com/reduxjs/reselect#identityfunctioncheck identityFunctionCheck}
* @see {@link https://github.com/reduxjs/reselect#2-per-selector-by-passing-an-identityfunctioncheck-option-directly-to-createselector per-selector-configuration}
*
* @since 5.0.0
*/
identityFunctionCheck: DevModeCheckFrequency;
}
/**
* The frequency of input stability checks.
* Represents execution information for development mode checks.
*
* @public
* @since 5.0.0
* @public
*/
type StabilityCheckFrequency = 'always' | 'once' | 'never';
type DevModeChecksExecutionInfo = {
[K in keyof DevModeChecks]: {
/**
* A boolean indicating whether the check should be executed.
*/
shouldRun: boolean;
/**
* The function to execute for the check.
*/
run: AnyFunction;
};
};
/**

@@ -315,14 +467,2 @@ * Determines the combined single "State" type (first arg) from all input selectors.

/**
* Any function with any arguments.
*
* @internal
*/
type AnyFunction = (...args: any[]) => any;
/**
* Any function with unknown arguments.
*
* @internal
*/
type UnknownFunction = (...args: unknown[]) => unknown;
/**
* Any Memoizer function. A memoizer is a function that accepts another function and returns it.

@@ -332,14 +472,15 @@ *

*
* @internal
* @public
*/
type UnknownMemoizer<FunctionType extends UnknownFunction = UnknownFunction> = (func: FunctionType, ...options: any[]) => FunctionType;
/**
* When a generic type parameter is using its default value of `never`, fallback to a different type.
* Extracts the options type for a memoization function based on its parameters.
* The first parameter of the function is expected to be the function to be memoized,
* followed by options for the memoization process.
*
* @template T - Type to be checked.
* @template FallbackTo - Type to fallback to if `T` resolves to `never`.
* @template MemoizeFunction - The type of the memoize function to be checked.
*
* @internal
* @public
*/
type FallbackIfNever<T, FallbackTo> = IfNever<T, FallbackTo, T>;
type MemoizeOptionsFromParameters<MemoizeFunction extends UnknownMemoizer> = (NonFunctionType<DropFirstParameter<MemoizeFunction>[0]> | FunctionType<DropFirstParameter<MemoizeFunction>[0]>) | (NonFunctionType<DropFirstParameter<MemoizeFunction>[number]> | FunctionType<DropFirstParameter<MemoizeFunction>[number]>)[];
/**

@@ -353,40 +494,71 @@ * Derive the type of memoize options object based on whether the memoize function itself was overridden.

*
* @internal
* @public
*/
type OverrideMemoizeOptions<MemoizeFunction extends UnknownMemoizer, OverrideMemoizeFunction extends UnknownMemoizer = never> = IfNever<OverrideMemoizeFunction, MemoizeOptionsFromParameters<MemoizeFunction>, MemoizeOptionsFromParameters<OverrideMemoizeFunction>>;
type OverrideMemoizeOptions<MemoizeFunction extends UnknownMemoizer, OverrideMemoizeFunction extends UnknownMemoizer = never> = IfNever<OverrideMemoizeFunction, Simplify<MemoizeOptionsFromParameters<MemoizeFunction>>, Simplify<MemoizeOptionsFromParameters<OverrideMemoizeFunction>>>;
/**
* Extracts the non-function part of a type.
* Extracts the additional properties or methods that a memoize function attaches to
* the function it memoizes (e.g., `clearCache`).
*
* @template T - The input type to be refined by excluding function types and index signatures.
* @template MemoizeFunction - The type of the memoize function to be checked.
*
* @public
*/
type ExtractMemoizerFields<MemoizeFunction extends UnknownMemoizer> = Simplify<OmitIndexSignature<ReturnType<MemoizeFunction>>>;
/**
* Represents the additional properties attached to a function memoized by `reselect`.
*
* `defaultMemoize`, `weakMapMemoize` and `autotrackMemoize` all return these properties.
*
* @see {@linkcode ExtractMemoizerFields ExtractMemoizerFields}
*
* @public
*/
type DefaultMemoizeFields = {
/**
* Clears the memoization cache associated with a memoized function.
* This method is typically used to reset the state of the cache, allowing
* for the garbage collection of previously memoized results and ensuring
* that future calls to the function recompute the results.
*/
clearCache: () => void;
resultsCount: () => number;
resetResultsCount: () => void;
};
/**
* Any function with any arguments.
*
* @internal
*/
type NonFunctionType<T> = OmitIndexSignature<Exclude<T, AnyFunction>>;
type AnyFunction = (...args: any[]) => any;
/**
* Extracts the function part of a type.
* Any function with unknown arguments.
*
* @template T - The input type to be refined by extracting function types.
* @internal
*/
type UnknownFunction = (...args: unknown[]) => unknown;
/**
* When a generic type parameter is using its default value of `never`, fallback to a different type.
*
* @template T - Type to be checked.
* @template FallbackTo - Type to fallback to if `T` resolves to `never`.
*
* @internal
*/
type FunctionType<T> = Extract<T, AnyFunction>;
type FallbackIfNever<T, FallbackTo> = IfNever<T, FallbackTo, T>;
/**
* Extracts the options type for a memoization function based on its parameters.
* The first parameter of the function is expected to be the function to be memoized,
* followed by options for the memoization process.
* Extracts the non-function part of a type.
*
* @template MemoizeFunction - The type of the memoize function to be checked.
* @template T - The input type to be refined by excluding function types and index signatures.
*
* @internal
*/
type MemoizeOptionsFromParameters<MemoizeFunction extends UnknownMemoizer> = (Simplify<NonFunctionType<DropFirstParameter<MemoizeFunction>[0]>> | FunctionType<DropFirstParameter<MemoizeFunction>[0]>) | (Simplify<NonFunctionType<DropFirstParameter<MemoizeFunction>[number]>> | FunctionType<DropFirstParameter<MemoizeFunction>[number]>)[];
type NonFunctionType<T> = Simplify<OmitIndexSignature<Exclude<T, AnyFunction>>>;
/**
* Extracts the additional fields that a memoize function attaches to
* the function it memoizes (e.g., `clearCache`).
* Extracts the function part of a type.
*
* @template MemoizeFunction - The type of the memoize function to be checked.
* @template T - The input type to be refined by extracting function types.
*
* @internal
*/
type ExtractMemoizerFields<MemoizeFunction extends UnknownMemoizer> = Simplify<OmitIndexSignature<ReturnType<MemoizeFunction>>>;
type FunctionType<T> = Extract<T, AnyFunction>;
/**

@@ -398,3 +570,3 @@ * Extracts the return type from all functions as a tuple.

type ExtractReturnType<FunctionsArray extends readonly AnyFunction[]> = {
[Index in keyof FunctionsArray]: FunctionsArray[Index] extends FunctionsArray[number] ? ReturnType<FunctionsArray[Index]> : never;
[Index in keyof FunctionsArray]: FunctionsArray[Index] extends FunctionsArray[number] ? FallbackIfUnknown<ReturnType<FunctionsArray[Index]>, any> : never;
};

@@ -424,6 +596,6 @@ /**

*/
type ArrayTail<TArray> = TArray extends readonly [
type ArrayTail<ArrayType> = ArrayType extends readonly [
unknown,
...infer TTail
] ? TTail : [];
...infer Tail
] ? Tail : [];
/**

@@ -475,3 +647,4 @@ * An alias for type `{}`. Represents any value that is not `null` or `undefined`.

*/
type UnionToIntersection<Union> = (Union extends unknown ? (distributedUnion: Union) => void : never) extends (mergedIntersection: infer Intersection) => void ? Intersection : never;
type UnionToIntersection<Union> = (Union extends unknown ? (distributedUnion: Union) => void : never) extends (mergedIntersection: infer Intersection) => void ? // The `& Union` is to allow indexing by the resulting type
Intersection & Union : never;
/**

@@ -505,2 +678,27 @@ * Code to convert a union of values into a tuple.

/**
* Create a type that makes the given keys required.
* The remaining keys are kept as is.
*
* @see {@link https://github.com/sindresorhus/type-fest/blob/main/source/set-required.d.ts Source}
*
* @internal
*/
type SetRequired<BaseType, Keys extends keyof BaseType> = Omit<BaseType, Keys> & Required<Pick<BaseType, Keys>>;
/**
* An if-else-like type that resolves depending on whether the given type is `unknown`.
* @see {@link https://github.com/sindresorhus/type-fest/blob/main/source/if-unknown.d.ts Source}
*
* @internal
*/
type IfUnknown<T, TypeIfUnknown, TypeIfNotUnknown> = unknown extends T ? [T] extends [null] ? TypeIfNotUnknown : TypeIfUnknown : TypeIfNotUnknown;
/**
* When a type is resolves to `unknown`, fallback to a different type.
*
* @template T - Type to be checked.
* @template FallbackTo - Type to fallback to if `T` resolves to `unknown`.
*
* @internal
*/
type FallbackIfUnknown<T, FallbackTo> = IfUnknown<T, FallbackTo, T>;
/**
* Useful to flatten the type output to improve type hints shown in editors.

@@ -512,3 +710,3 @@ * And also to transform an interface into a type to aide with assignability.

*/
type Simplify<T> = {
type Simplify<T> = T extends AnyFunction ? T : {
[KeyType in keyof T]: T[KeyType];

@@ -564,3 +762,3 @@ } & AnyNonNullishValue;

*
* const createSelectorAutotrack = createSelectorCreator(autotrackMemoize)
* const createSelectorAutotrack = createSelectorCreator({ memoize: autotrackMemoize })
*

@@ -575,2 +773,4 @@ * const selectTodoIds = createSelectorAutotrack(

*
* @see {@link https://github.com/reduxjs/reselect#unstable_autotrackmemoizefunc---since-500 autotrackMemoize}
*
* @since 5.0.0

@@ -582,2 +782,4 @@ * @public

clearCache: () => void;
resultsCount: () => number;
resetResultsCount: () => void;
};

@@ -589,7 +791,7 @@

* @template MemoizeFunction - The type of the memoize function that is used to memoize the `resultFunc` inside `createSelector` (e.g., `defaultMemoize` or `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., `defaultMemoize` or `weakMapMemoize`). If none is explicitly provided, `defaultMemoize` will be used.
* @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., `defaultMemoize` or `weakMapMemoize`). If none is explicitly provided, `weakMapMemoize` will be used.
*
* @public
*/
interface CreateSelectorFunction<MemoizeFunction extends UnknownMemoizer = typeof defaultMemoize, ArgsMemoizeFunction extends UnknownMemoizer = typeof defaultMemoize> {
interface CreateSelectorFunction<MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize, ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize> {
/**

@@ -606,3 +808,3 @@ * Creates a memoized selector function.

*
* @see {@link https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc-selectoroptions createSelector}
* @see {@link https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc-createselectoroptions createSelector}
*/

@@ -624,3 +826,3 @@ <InputSelectors extends SelectorArray, Result>(...createSelectorArgs: [

*
* @see {@link https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc-selectoroptions createSelector}
* @see {@link https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc-createselectoroptions createSelector}
*/

@@ -630,3 +832,3 @@ <InputSelectors extends SelectorArray, Result, OverrideMemoizeFunction extends UnknownMemoizer = MemoizeFunction, OverrideArgsMemoizeFunction extends UnknownMemoizer = ArgsMemoizeFunction>(...createSelectorArgs: [

combiner: Combiner<InputSelectors, Result>,
createSelectorOptions: Partial<CreateSelectorOptions<MemoizeFunction, ArgsMemoizeFunction, OverrideMemoizeFunction, OverrideArgsMemoizeFunction>>
createSelectorOptions: Simplify<CreateSelectorOptions<MemoizeFunction, ArgsMemoizeFunction, OverrideMemoizeFunction, OverrideArgsMemoizeFunction>>
]): OutputSelector<InputSelectors, Result, OverrideMemoizeFunction, OverrideArgsMemoizeFunction> & InterruptRecursion;

@@ -646,44 +848,7 @@ /**

*
* @see {@link https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc-selectoroptions createSelector}
* @see {@link https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc-createselectoroptions createSelector}
*/
<InputSelectors extends SelectorArray, Result, OverrideMemoizeFunction extends UnknownMemoizer = MemoizeFunction, OverrideArgsMemoizeFunction extends UnknownMemoizer = ArgsMemoizeFunction>(inputSelectors: [...InputSelectors], combiner: Combiner<InputSelectors, Result>, createSelectorOptions?: Partial<CreateSelectorOptions<MemoizeFunction, ArgsMemoizeFunction, OverrideMemoizeFunction, OverrideArgsMemoizeFunction>>): OutputSelector<InputSelectors, Result, OverrideMemoizeFunction, OverrideArgsMemoizeFunction> & InterruptRecursion;
<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;
}
/**
* In development mode, an extra check is conducted on your input selectors.
* It runs your input selectors an extra time with the same arguments, and
* warns in the console if they return a different result _(based on your `memoize` method)_.
*
* This function allows you to override this setting for all of your selectors.
*
* **Note**: This setting can still be overridden per selector inside `createSelector`'s `options` object.
* See {@link https://github.com/reduxjs/reselect#per-selector-configuration per-selector-configuration}
* and {@linkcode CreateSelectorOptions.inputStabilityCheck inputStabilityCheck} for more details.
*
* _The input stability check does not run in production builds._
*
* @param inputStabilityCheckFrequency - How often the `inputStabilityCheck` should run for all selectors.
*
* @example
* ```ts
* import { setInputStabilityCheckEnabled } from 'reselect'
import { assert } from './autotrackMemoize/utils';
import { OutputSelectorFields, Mapped } from './types';
*
* // Run only the first time the selector is called. (default)
* setInputStabilityCheckEnabled('once')
*
* // Run every time the selector is called.
* setInputStabilityCheckEnabled('always')
*
* // Never run the input stability check.
* setInputStabilityCheckEnabled('never')
* ```
* @see {@link https://github.com/reduxjs/reselect#development-only-checks development-only-checks}
* @see {@link https://github.com/reduxjs/reselect#global-configuration global-configuration}
*
* @since 5.0.0
* @public
*/
declare function setInputStabilityCheckEnabled(inputStabilityCheckFrequency: StabilityCheckFrequency): void;
/**
* Creates a selector creator function with the specified memoization function and options for customizing memoization behavior.

@@ -714,5 +879,5 @@ *

* @template MemoizeFunction - The type of the memoize function that is used to memoize the `resultFunc` inside `createSelector` (e.g., `defaultMemoize` or `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., `defaultMemoize` or `weakMapMemoize`). If none is explicitly provided, `defaultMemoize` will be used.
* @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., `defaultMemoize` or `weakMapMemoize`). If none is explicitly provided, `weakMapMemoize` will be used.
*
* @see {@link https://github.com/reduxjs/reselect#createselectorcreatormemoize-memoizeoptions createSelectorCreator}
* @see {@link https://github.com/reduxjs/reselect#createselectorcreatormemoize--options-memoizeoptions createSelectorCreator}
*

@@ -722,3 +887,3 @@ * @since 5.0.0

*/
declare function createSelectorCreator<MemoizeFunction extends UnknownMemoizer, ArgsMemoizeFunction extends UnknownMemoizer = typeof defaultMemoize>(options: CreateSelectorOptions<typeof defaultMemoize, typeof defaultMemoize, MemoizeFunction, ArgsMemoizeFunction>): CreateSelectorFunction<MemoizeFunction, ArgsMemoizeFunction>;
declare function createSelectorCreator<MemoizeFunction extends UnknownMemoizer, ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize>(options: Simplify<SetRequired<CreateSelectorOptions<typeof weakMapMemoize, typeof weakMapMemoize, MemoizeFunction, ArgsMemoizeFunction>, 'memoize'>>): CreateSelectorFunction<MemoizeFunction, ArgsMemoizeFunction>;
/**

@@ -747,3 +912,3 @@ * Creates a selector creator function with the specified memoization function and options for customizing memoization behavior.

*
* @see {@link https://github.com/reduxjs/reselect#createselectorcreatormemoize-memoizeoptions createSelectorCreator}
* @see {@link https://github.com/reduxjs/reselect#createselectorcreatormemoize--options-memoizeoptions createSelectorCreator}
*

@@ -758,10 +923,62 @@ * @public

*
* @see {@link https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc-selectoroptions createSelector}
* @see {@link https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc-createselectoroptions createSelector}
*
* @public
*/
declare const createSelector: CreateSelectorFunction<typeof defaultMemoize, typeof defaultMemoize>;
declare const createSelector: CreateSelectorFunction<typeof weakMapMemoize, typeof weakMapMemoize>;
/**
* Runs a simple reference equality check.
* What {@linkcode defaultMemoize defaultMemoize} uses by default.
*
* @public
*/
declare const defaultEqualityCheck: EqualityFn;
/**
* @public
*/
interface DefaultMemoizeOptions<T = any> {
/**
* Used to compare the individual arguments of the provided calculation function.
*
* @default defaultEqualityCheck
*/
equalityCheck?: EqualityFn;
/**
* If provided, used to compare a newly generated output value against previous values in the cache.
* If a match is found, the old value is returned. This addresses the common
* ```ts
* todos.map(todo => todo.id)
* ```
* use case, where an update to another field in the original data causes a recalculation
* due to changed references, but the output is still effectively the same.
*/
resultEqualityCheck?: EqualityFn<T>;
/**
* The cache size for the selector. If greater than 1, the selector will use an LRU cache internally.
*
* @default 1
*/
maxSize?: number;
}
/**
* The standard memoize function used by `createSelector`.
* @param func - The function to be memoized.
* @param equalityCheckOrOptions - Either an equality check function or an options object.
* @returns A memoized function with a `.clearCache()` method attached.
*
* @template Func - The type of the function that is memoized.
*
* @see {@link https://github.com/reduxjs/reselect#defaultmemoizefunc-equalitycheckoroptions--defaultequalitycheck defaultMemoize}
*
* @public
*/
declare function defaultMemoize<Func extends AnyFunction>(func: Func, equalityCheckOrOptions?: EqualityFn | DefaultMemoizeOptions<ReturnType<Func>>): Func & {
clearCache: () => void;
resultsCount: () => number;
resetResultsCount: () => void;
};
/**
*
* @WIP

@@ -795,3 +1012,3 @@ */

*
* @see {@link https://github.com/reduxjs/reselect#createstructuredselectorinputselectors-selectorcreator--createselector createStructuredSelector}
* @see {@link https://github.com/reduxjs/reselect#createstructuredselector-inputselectorsobject--selectorcreator--createselector createStructuredSelector}
*

@@ -802,7 +1019,6 @@ * @public

/**
* A convenience function for a common pattern that arises when using Reselect.
* The selector passed to a `connect` decorator often just takes the
* values of its input selectors and maps them to keys in an object.
* A convenience function that simplifies returning an object
* made up of selector results.
*
* @param selectorMap - A key value pair consisting of input selectors.
* @param inputSelectorsObject - A key value pair consisting of input selectors.
* @param selectorCreator - A custom selector creator function. It defaults to `createSelector`.

@@ -816,54 +1032,18 @@ * @returns A memoized structured selector.

*
* interface State {
* interface RootState {
* todos: {
* id: number
* completed: boolean
* title: string
* description: string
* completed: boolean
* }[]
* alerts: {
* id: number
* message: string
* type: 'reminder' | 'notification'
* read: boolean
* }[]
* alerts: { id: number; read: boolean }[]
* }
*
* const state: State = {
* todos: [
* {
* id: 0,
* title: 'Buy groceries',
* description: 'Milk, bread, eggs, and fruits',
* completed: false
* },
* {
* id: 1,
* title: 'Schedule dentist appointment',
* description: 'Check available slots for next week',
* completed: true
* }
* ],
* alerts: [
* {
* id: 0,
* message: 'You have an upcoming meeting at 3 PM.',
* type: 'reminder',
* read: false
* },
* {
* id: 1,
* message: 'New software update available.',
* type: 'notification',
* read: true
* }
* ]
* }
*
* // This:
* const structuredSelector = createStructuredSelector(
* {
* allTodos: (state: State) => state.todos,
* allAlerts: (state: State) => state.alerts,
* selectedTodo: (state: State, id: number) => state.todos[id]
* todos: (state: RootState) => state.todos,
* alerts: (state: RootState) => state.alerts,
* todoById: (state: RootState, id: number) => state.todos[id]
* },

@@ -876,11 +1056,11 @@ * createSelector

* [
* (state: State) => state.todos,
* (state: State) => state.alerts,
* (state: State, id: number) => state.todos[id]
* (state: RootState) => state.todos,
* (state: RootState) => state.alerts,
* (state: RootState, id: number) => state.todos[id]
* ],
* (allTodos, allAlerts, selectedTodo) => {
* (todos, alerts, todoById) => {
* return {
* allTodos,
* allAlerts,
* selectedTodo
* todos,
* alerts,
* todoById
* }

@@ -908,29 +1088,56 @@ * }

* @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 `defaultMemoize`.
* @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 `defaultMemoize`.
* @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://github.com/reduxjs/reselect#createstructuredselectorinputselectors-selectorcreator--createselector createStructuredSelector}
* @see {@link https://github.com/reduxjs/reselect#createstructuredselector-inputselectorsobject--selectorcreator--createselector createStructuredSelector}
*/
<InputSelectorsObject extends SelectorsObject, MemoizeFunction extends UnknownMemoizer = typeof defaultMemoize, ArgsMemoizeFunction extends UnknownMemoizer = typeof defaultMemoize>(selectorMap: InputSelectorsObject, selectorCreator?: CreateSelectorFunction<MemoizeFunction, ArgsMemoizeFunction>): OutputSelector<ObjectValuesToTuple<InputSelectorsObject>, SelectorsMap<InputSelectorsObject>, MemoizeFunction, ArgsMemoizeFunction>;
<InputSelectorsObject extends SelectorsObject, MemoizeFunction extends UnknownMemoizer = typeof defaultMemoize, ArgsMemoizeFunction extends UnknownMemoizer = typeof defaultMemoize>(inputSelectorsObject: InputSelectorsObject, selectorCreator?: CreateSelectorFunction<MemoizeFunction, ArgsMemoizeFunction>): OutputSelector<ObjectValuesToTuple<InputSelectorsObject>, Simplify<SelectorsMap<InputSelectorsObject>>, MemoizeFunction, ArgsMemoizeFunction> & InterruptRecursion;
}
/**
* A convenience function for a common pattern that arises when using Reselect.
* The selector passed to a `connect` decorator often just takes the values of its input selectors
* and maps them to keys in an object.
* A convenience function that simplifies returning an object
* made up of selector results.
*
* @example
* <caption>Simple Use Case</caption>
* <caption>Modern Use Case</caption>
* ```ts
* const selectA = state => state.a
* const selectB = state => state.b
* import { createSelector, createStructuredSelector } from 'reselect'
*
* // 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
* }))
* 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
* }
* }
* )
* ```
*
* @see {@link https://github.com/reduxjs/reselect#createstructuredselectorinputselectors-selectorcreator--createselector createStructuredSelector}
* @see {@link https://github.com/reduxjs/reselect#createstructuredselector-inputselectorsobject--selectorcreator--createselector createStructuredSelector}
*

@@ -942,69 +1149,47 @@ * @public

/**
* Creates a tree of `WeakMap`-based cache nodes based on the identity of the
* arguments it's been called with (in this case, the extracted values from your input selectors).
* This allows `weakmapMemoize` to have an effectively infinite cache size.
* Cache results will be kept in memory as long as references to the arguments still exist,
* and then cleared out as the arguments are garbage-collected.
* Overrides the development mode checks settings for all selectors.
*
* __Design Tradeoffs for `weakmapMemoize`:__
* - Pros:
* - It has an effectively infinite cache size, but you have no control over
* how long values are kept in cache as it's based on garbage collection and `WeakMap`s.
* - Cons:
* - There's currently no way to alter the argument comparisons.
* They're based on strict reference equality.
* - It's roughly the same speed as `defaultMemoize`, although likely a fraction slower.
* Reselect performs additional checks in development mode to help identify and
* warn about potential issues in selector behavior. This function allows you to
* customize the behavior of these checks across all selectors in your application.
*
* __Use Cases for `weakmapMemoize`:__
* - This memoizer is likely best used for cases where you need to call the
* same selector instance with many different arguments, such as a single
* selector instance that is used in a list item component and called with
* item IDs like:
* ```ts
* useSelector(state => selectSomeData(state, props.category))
* ```
* @param func - The function to be memoized.
* @returns A memoized function with a `.clearCache()` method attached.
* **Note**: This setting can still be overridden per selector inside `createSelector`'s `options` object.
* See {@link https://github.com/reduxjs/reselect#2-per-selector-by-passing-an-identityfunctioncheck-option-directly-to-createselector per-selector-configuration}
* and {@linkcode CreateSelectorOptions.identityFunctionCheck identityFunctionCheck} for more details.
*
* @example
* <caption>Using `createSelector`</caption>
* ```ts
* import { createSelector, weakMapMemoize } from 'reselect'
* _The development mode checks do not run in production builds._
*
* const selectTodoById = createSelector(
* [
* (state: RootState) => state.todos,
* (state: RootState, id: number) => id
* ],
* (todos) => todos[id],
* { memoize: weakMapMemoize }
* )
* ```
* @param devModeChecks - An object specifying the desired settings for development mode checks. You can provide partial overrides. Unspecified settings will retain their current values.
*
* @example
* <caption>Using `createSelectorCreator`</caption>
* ```ts
* import { createSelectorCreator, weakMapMemoize } from 'reselect'
* import { setGlobalDevModeChecks } from 'reselect'
import { DevModeChecks } from '../types';
*
* const createSelectorWeakmap = createSelectorCreator(weakMapMemoize)
* // Run only the first time the selector is called. (default)
* setGlobalDevModeChecks({ inputStabilityCheck: 'once' })
*
* const selectTodoById = createSelectorWeakmap(
* [
* (state: RootState) => state.todos,
* (state: RootState, id: number) => id
* ],
* (todos) => todos[id]
* )
* // Run every time the selector is called.
* setGlobalDevModeChecks({ inputStabilityCheck: 'always' })
*
* // Never run the input stability check.
* setGlobalDevModeChecks({ inputStabilityCheck: 'never' })
*
* // Run only the first time the selector is called. (default)
* setGlobalDevModeChecks({ identityFunctionCheck: 'once' })
*
* // Run every time the selector is called.
* setGlobalDevModeChecks({ identityFunctionCheck: 'always' })
*
* // Never run the identity function check.
* setGlobalDevModeChecks({ identityFunctionCheck: 'never' })
* ```
* @see {@link https://github.com/reduxjs/reselect#debugging-tools debugging-tools}
* @see {@link https://github.com/reduxjs/reselect#1-globally-through-setglobaldevmodechecks global-configuration}
*
* @template Func - The type of the function that is memoized.
*
* @since 5.0.0
* @public
* @experimental
*/
declare function weakMapMemoize<Func extends AnyFunction>(func: Func): Func & {
clearCache: () => void;
};
declare const setGlobalDevModeChecks: (devModeChecks: Partial<DevModeChecks>) => void;
export { Combiner, CreateSelectorFunction, CreateSelectorOptions, DefaultMemoizeOptions, EqualityFn, GetParamsFromSelectors, GetStateFromSelectors, OutputParametricSelector, OutputSelector, OutputSelectorFields, ParametricSelector, Selector, SelectorArray, SelectorResultArray, StabilityCheckFrequency, StructuredSelectorCreator, TypedStructuredSelectorCreator, createSelector, createSelectorCreator, createStructuredSelector, defaultEqualityCheck, defaultMemoize, setInputStabilityCheckEnabled, autotrackMemoize as unstable_autotrackMemoize, weakMapMemoize };
export { Combiner, CreateSelectorFunction, CreateSelectorOptions, DefaultMemoizeFields, DefaultMemoizeOptions, DevModeCheckFrequency, DevModeChecks, DevModeChecksExecutionInfo, EqualityFn, ExtractMemoizerFields, GetParamsFromSelectors, GetStateFromSelectors, MemoizeOptionsFromParameters, OutputSelector, OutputSelectorFields, OverrideMemoizeOptions, Selector, SelectorArray, SelectorResultArray, StructuredSelectorCreator, TypedStructuredSelectorCreator, UnknownMemoizer, createSelector, createSelectorCreator, createStructuredSelector, defaultEqualityCheck, defaultMemoize, setGlobalDevModeChecks, autotrackMemoize as unstable_autotrackMemoize, weakMapMemoize };

@@ -22,3 +22,47 @@ 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) {
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."
);
}
};
// src/devModeChecks/inputStabilityCheck.ts
var runInputStabilityCheck = (inputSelectorResultsObject, options, inputSelectorArgs) => {
const { memoize, memoizeOptions } = options;
const { inputSelectorResults, inputSelectorResultsCopy } = inputSelectorResultsObject;
const createAnEmptyObject = memoize(() => ({}), ...memoizeOptions);
const areInputSelectorResultsEqual = createAnEmptyObject.apply(null, inputSelectorResults) === createAnEmptyObject.apply(null, inputSelectorResultsCopy);
if (!areInputSelectorResultsEqual) {
console.warn(
"An input selector returned a different result when passed same arguments.\nThis means your output selector will likely run more frequently than intended.\nAvoid returning a new reference inside your input selector, e.g.\n`createSelector([state => state.todos.map(todo => todo.id)], todoIds => todoIds.length)`",
{
arguments: inputSelectorArgs,
firstInputs: inputSelectorResults,
secondInputs: inputSelectorResultsCopy
}
);
}
};
// src/devModeChecks/setGlobalDevModeChecks.ts
var globalDevModeChecks = {
inputStabilityCheck: "once",
identityFunctionCheck: "once"
};
var setGlobalDevModeChecks = (devModeChecks) => {
Object.assign(globalDevModeChecks, devModeChecks);
};
// src/utils.ts
var NOT_FOUND = "NOT_FOUND";
function assertIsFunction(func, errorMessage = `expected a function, instead received ${typeof func}`) {

@@ -61,20 +105,14 @@ if (typeof func !== "function") {

}
function runStabilityCheck(inputSelectorResultsObject, options, inputSelectorArgs) {
const { memoize, memoizeOptions } = options;
const { inputSelectorResults, inputSelectorResultsCopy } = inputSelectorResultsObject;
const createAnEmptyObject = memoize(() => ({}), ...memoizeOptions);
const areInputSelectorResultsEqual = createAnEmptyObject.apply(null, inputSelectorResults) === createAnEmptyObject.apply(null, inputSelectorResultsCopy);
if (!areInputSelectorResultsEqual) {
console.warn(
"An input selector returned a different result when passed same arguments.\nThis means your output selector will likely run more frequently than intended.\nAvoid returning a new reference inside your input selector, e.g.\n`createSelector([(arg1, arg2) => ({ arg1, arg2 })],(arg1, arg2) => {})`",
{
arguments: inputSelectorArgs,
firstInputs: inputSelectorResults,
secondInputs: inputSelectorResultsCopy
}
);
}
}
var shouldRunInputStabilityCheck = (inputStabilityCheck, firstRun) => {
return inputStabilityCheck === "always" || inputStabilityCheck === "once" && firstRun;
var getDevModeChecksExecutionInfo = (firstRun, devModeChecks) => {
const { identityFunctionCheck, inputStabilityCheck } = __spreadValues(__spreadValues({}, globalDevModeChecks), devModeChecks);
return {
identityFunctionCheck: {
shouldRun: identityFunctionCheck === "always" || identityFunctionCheck === "once" && firstRun,
run: runIdentityFunctionCheck
},
inputStabilityCheck: {
shouldRun: inputStabilityCheck === "always" || inputStabilityCheck === "once" && firstRun,
run: runInputStabilityCheck
}
};
};

@@ -358,3 +396,2 @@

// src/defaultMemoize.ts
var NOT_FOUND = "NOT_FOUND";
function createSingletonCache(equals) {

@@ -435,2 +472,3 @@ let entry;

const comparator = createCacheKeyComparator(equalityCheck);
let resultsCount = 0;
const cache = maxSize === 1 ? createSingletonCache(comparator) : createLruCache(maxSize, comparator);

@@ -441,2 +479,3 @@ function memoized() {

value = func.apply(null, arguments);
resultsCount++;
if (resultEqualityCheck) {

@@ -449,2 +488,3 @@ const entries = cache.getEntries();

value = matchingEntry.value;
resultsCount--;
}

@@ -458,3 +498,8 @@ }

cache.clear();
memoized.resetResultsCount();
};
memoized.resultsCount = () => resultsCount;
memoized.resetResultsCount = () => {
resultsCount = 0;
};
return memoized;

@@ -481,11 +526,98 @@ }

}
memoized.clearCache = () => cache.clear();
memoized.clearCache = () => {
return cache.clear();
};
return memoized;
}
// src/weakMapMemoize.ts
var StrongRef = class {
constructor(value) {
this.value = value;
}
deref() {
return this.value;
}
};
var Ref = WeakRef != null ? WeakRef : StrongRef;
var UNTERMINATED = 0;
var TERMINATED = 1;
function createCacheNode() {
return {
s: UNTERMINATED,
v: void 0,
o: null,
p: null
};
}
function weakMapMemoize(func, options = {}) {
let fnNode = createCacheNode();
const { resultEqualityCheck } = options;
let lastResult;
let resultsCount = 0;
function memoized() {
var _a;
let cacheNode = fnNode;
const { length } = arguments;
for (let i = 0, l = length; i < l; i++) {
const arg = arguments[i];
if (typeof arg === "function" || typeof arg === "object" && arg !== null) {
let objectCache = cacheNode.o;
if (objectCache === null) {
cacheNode.o = objectCache = /* @__PURE__ */ new WeakMap();
}
const objectNode = objectCache.get(arg);
if (objectNode === void 0) {
cacheNode = createCacheNode();
objectCache.set(arg, cacheNode);
} else {
cacheNode = objectNode;
}
} else {
let primitiveCache = cacheNode.p;
if (primitiveCache === null) {
cacheNode.p = primitiveCache = /* @__PURE__ */ new Map();
}
const primitiveNode = primitiveCache.get(arg);
if (primitiveNode === void 0) {
cacheNode = createCacheNode();
primitiveCache.set(arg, cacheNode);
} else {
cacheNode = primitiveNode;
}
}
}
const terminatedNode = cacheNode;
let result;
if (cacheNode.s === TERMINATED) {
result = cacheNode.v;
} else {
result = func.apply(null, arguments);
resultsCount++;
}
terminatedNode.s = TERMINATED;
if (resultEqualityCheck) {
const lastResultValue = (_a = lastResult == null ? void 0 : lastResult.deref()) != null ? _a : lastResult;
if (lastResultValue != null && resultEqualityCheck(lastResultValue, result)) {
result = lastResultValue;
resultsCount !== 0 && resultsCount--;
}
const needsWeakRef = typeof result === "object" && result !== null || typeof result === "function";
lastResult = needsWeakRef ? new Ref(result) : result;
}
terminatedNode.v = result;
return result;
}
memoized.clearCache = () => {
fnNode = createCacheNode();
memoized.resetResultsCount();
};
memoized.resultsCount = () => resultsCount;
memoized.resetResultsCount = () => {
resultsCount = 0;
};
return memoized;
}
// src/createSelectorCreator.ts
var globalStabilityCheck = "once";
function setInputStabilityCheckEnabled(inputStabilityCheckFrequency) {
globalStabilityCheck = inputStabilityCheckFrequency;
}
function createSelectorCreator(memoizeOrOptions, ...memoizeOptionsFromArgs) {

@@ -498,2 +630,3 @@ const createSelectorCreatorOptions = typeof memoizeOrOptions === "function" ? {

let recomputations = 0;
let dependencyRecomputations = 0;
let lastResult;

@@ -514,5 +647,5 @@ let directlyPassedOptions = {};

memoizeOptions = [],
argsMemoize = defaultMemoize,
argsMemoize = weakMapMemoize,
argsMemoizeOptions = [],
inputStabilityCheck = globalStabilityCheck
devModeChecks = {}
} = combinedOptions;

@@ -531,2 +664,3 @@ const finalMemoizeOptions = ensureIsArray(memoizeOptions);

const selector = argsMemoize(function dependenciesChecker() {
dependencyRecomputations++;
const inputSelectorResults = collectInputSelectorResults(

@@ -536,12 +670,20 @@ dependencies,

);
if (process.env.NODE_ENV !== "production" && shouldRunInputStabilityCheck(inputStabilityCheck, firstRun)) {
const inputSelectorResultsCopy = collectInputSelectorResults(
dependencies,
arguments
);
runStabilityCheck(
{ inputSelectorResults, inputSelectorResultsCopy },
{ memoize, memoizeOptions: finalMemoizeOptions },
arguments
);
if (process.env.NODE_ENV !== "production") {
const { identityFunctionCheck, inputStabilityCheck } = getDevModeChecksExecutionInfo(firstRun, devModeChecks);
if (identityFunctionCheck.shouldRun) {
identityFunctionCheck.run(
resultFunc
);
}
if (inputStabilityCheck.shouldRun) {
const inputSelectorResultsCopy = collectInputSelectorResults(
dependencies,
arguments
);
inputStabilityCheck.run(
{ inputSelectorResults, inputSelectorResultsCopy },
{ memoize, memoizeOptions: finalMemoizeOptions },
arguments
);
}
if (firstRun)

@@ -557,5 +699,11 @@ firstRun = false;

dependencies,
dependencyRecomputations: () => dependencyRecomputations,
resetDependencyRecomputations: () => {
dependencyRecomputations = 0;
},
lastResult: () => lastResult,
recomputations: () => recomputations,
resetRecomputations: () => recomputations = 0,
resetRecomputations: () => {
recomputations = 0;
},
memoize,

@@ -567,3 +715,3 @@ argsMemoize

}
var createSelector = /* @__PURE__ */ createSelectorCreator(defaultMemoize);
var createSelector = /* @__PURE__ */ createSelectorCreator(weakMapMemoize);

@@ -589,64 +737,2 @@ // src/createStructuredSelector.ts

};
// src/weakMapMemoize.ts
var UNTERMINATED = 0;
var TERMINATED = 1;
function createCacheNode() {
return {
s: UNTERMINATED,
// status, represents whether the cached computation returned a value or threw an error
v: void 0,
// value, either the cached result or an error, depending on s
o: null,
// object cache, a WeakMap where non-primitive arguments are stored
p: null
// primitive cache, a regular Map where primitive arguments are stored.
};
}
function weakMapMemoize(func) {
let fnNode = createCacheNode();
function memoized() {
let cacheNode = fnNode;
for (let i = 0, l = arguments.length; i < l; i++) {
const arg = arguments[i];
if (typeof arg === "function" || typeof arg === "object" && arg !== null) {
let objectCache = cacheNode.o;
if (objectCache === null) {
cacheNode.o = objectCache = /* @__PURE__ */ new WeakMap();
}
const objectNode = objectCache.get(arg);
if (objectNode === void 0) {
cacheNode = createCacheNode();
objectCache.set(arg, cacheNode);
} else {
cacheNode = objectNode;
}
} else {
let primitiveCache = cacheNode.p;
if (primitiveCache === null) {
cacheNode.p = primitiveCache = /* @__PURE__ */ new Map();
}
const primitiveNode = primitiveCache.get(arg);
if (primitiveNode === void 0) {
cacheNode = createCacheNode();
primitiveCache.set(arg, cacheNode);
} else {
cacheNode = primitiveNode;
}
}
}
if (cacheNode.s === TERMINATED) {
return cacheNode.v;
}
const result = func.apply(null, arguments);
const terminatedNode = cacheNode;
terminatedNode.s = TERMINATED;
terminatedNode.v = result;
return result;
}
memoized.clearCache = () => {
fnNode = createCacheNode();
};
return memoized;
}
export {

@@ -658,3 +744,3 @@ createSelector,

defaultMemoize,
setInputStabilityCheckEnabled,
setGlobalDevModeChecks,
autotrackMemoize as unstable_autotrackMemoize,

@@ -661,0 +747,0 @@ weakMapMemoize

{
"name": "reselect",
"version": "5.0.0-beta.1",
"version": "5.0.0-rc.0",
"description": "Selectors for Redux.",

@@ -30,5 +30,7 @@ "main": "./dist/cjs/reselect.cjs",

"prepack": "yarn build",
"bench": "vitest --run bench",
"bench": "vitest --run bench --mode production",
"test": "node --expose-gc ./node_modules/vitest/dist/cli-wrapper.js run",
"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",
"test:typescript": "tsc --noEmit -p typescript_test/tsconfig.json"

@@ -52,11 +54,17 @@ },

"devDependencies": {
"@reduxjs/toolkit": "^1.9.3",
"@reduxjs/toolkit": "^2.0.0-rc.1",
"@testing-library/react": "^14.1.2",
"@types/lodash": "^4.14.175",
"@types/react": "^18.2.38",
"@types/react-dom": "^18.2.17",
"@types/shelljs": "^0.8.11",
"@typescript-eslint/eslint-plugin": "5.1.0",
"@typescript-eslint/eslint-plugin-tslint": "5.1.0",
"@typescript-eslint/parser": "5.1.0",
"@typescript-eslint/eslint-plugin": "^6",
"@typescript-eslint/eslint-plugin-tslint": "^6",
"@typescript-eslint/parser": "^6",
"@typescript/analyze-trace": "^0.10.1",
"eslint": "^8.0.1",
"eslint-plugin-react": "^7.26.1",
"eslint-plugin-typescript": "0.14.0",
"jsdom": "^23.0.0",
"lodash": "^4.17.21",
"lodash.memoize": "^4.1.2",

@@ -68,9 +76,9 @@ "memoize-one": "^6.0.0",

"react-dom": "^18.2.0",
"react-redux": "^8.0.2",
"react-redux": "^9.0.0-rc.0",
"rimraf": "^3.0.2",
"shelljs": "^0.8.5",
"tsup": "^6.7.0",
"typescript": "^4.9",
"typescript": "5.2",
"vitest": "^0.34"
}
}

@@ -6,4 +6,4 @@ // Original autotracking implementation source:

// - https://v5.chriskrycho.com/journal/autotracking-elegant-dx-via-cutting-edge-cs/
import type { EqualityFn } from '@internal/types'
import { assertIsFunction } from '@internal/utils'
import type { EqualityFn } from '../types'
import { assertIsFunction } from '../utils'

@@ -10,0 +10,0 @@ // The global revision clock. Every time state changes, the clock increments.

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

defaultEqualityCheck
} from '@internal/defaultMemoize'
import type { AnyFunction } from '@internal/types'
} from '../defaultMemoize'
import type { AnyFunction, DefaultMemoizeFields, Simplify } from '../types'
import { createCache } from './autotracking'

@@ -59,3 +59,3 @@

*
* const createSelectorAutotrack = createSelectorCreator(autotrackMemoize)
* const createSelectorAutotrack = createSelectorCreator({ memoize: autotrackMemoize })
*

@@ -70,2 +70,4 @@ * const selectTodoIds = createSelectorAutotrack(

*
* @see {@link https://github.com/reduxjs/reselect#unstable_autotrackmemoizefunc---since-500 autotrackMemoize}
*
* @since 5.0.0

@@ -99,5 +101,7 @@ * @public

memoized.clearCache = () => cache.clear()
memoized.clearCache = () => {
return cache.clear()
}
return memoized as Func & { clearCache: () => void }
return memoized as Func & Simplify<DefaultMemoizeFields>
}

@@ -1,3 +0,2 @@

import type { OutputSelector, Selector, SelectorArray } from 'reselect'
import { defaultMemoize } from './defaultMemoize'
import { weakMapMemoize } from './weakMapMemoize'

@@ -12,3 +11,7 @@ import type {

InterruptRecursion,
StabilityCheckFrequency,
OutputSelector,
Selector,
SelectorArray,
SetRequired,
Simplify,
UnknownMemoizer

@@ -22,4 +25,3 @@ } from './types'

getDependencies,
runStabilityCheck,
shouldRunInputStabilityCheck
getDevModeChecksExecutionInfo
} from './utils'

@@ -31,3 +33,3 @@

* @template MemoizeFunction - The type of the memoize function that is used to memoize the `resultFunc` inside `createSelector` (e.g., `defaultMemoize` or `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., `defaultMemoize` or `weakMapMemoize`). If none is explicitly provided, `defaultMemoize` will be used.
* @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., `defaultMemoize` or `weakMapMemoize`). If none is explicitly provided, `weakMapMemoize` will be used.
*

@@ -37,4 +39,4 @@ * @public

export interface CreateSelectorFunction<
MemoizeFunction extends UnknownMemoizer = typeof defaultMemoize,
ArgsMemoizeFunction extends UnknownMemoizer = typeof defaultMemoize
MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize,
ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize
> {

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

*
* @see {@link https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc-selectoroptions createSelector}
* @see {@link https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc-createselectoroptions createSelector}
*/

@@ -79,3 +81,3 @@ <InputSelectors extends SelectorArray, Result>(

*
* @see {@link https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc-selectoroptions createSelector}
* @see {@link https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc-createselectoroptions createSelector}
*/

@@ -91,3 +93,3 @@ <

combiner: Combiner<InputSelectors, Result>,
createSelectorOptions: Partial<
createSelectorOptions: Simplify<
CreateSelectorOptions<

@@ -122,3 +124,3 @@ MemoizeFunction,

*
* @see {@link https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc-selectoroptions createSelector}
* @see {@link https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc-createselectoroptions createSelector}
*/

@@ -133,3 +135,3 @@ <

combiner: Combiner<InputSelectors, Result>,
createSelectorOptions?: Partial<
createSelectorOptions?: Simplify<
CreateSelectorOptions<

@@ -151,47 +153,3 @@ MemoizeFunction,

let globalStabilityCheck: StabilityCheckFrequency = 'once'
/**
* In development mode, an extra check is conducted on your input selectors.
* It runs your input selectors an extra time with the same arguments, and
* warns in the console if they return a different result _(based on your `memoize` method)_.
*
* This function allows you to override this setting for all of your selectors.
*
* **Note**: This setting can still be overridden per selector inside `createSelector`'s `options` object.
* See {@link https://github.com/reduxjs/reselect#per-selector-configuration per-selector-configuration}
* and {@linkcode CreateSelectorOptions.inputStabilityCheck inputStabilityCheck} for more details.
*
* _The input stability check does not run in production builds._
*
* @param inputStabilityCheckFrequency - How often the `inputStabilityCheck` should run for all selectors.
*
* @example
* ```ts
* import { setInputStabilityCheckEnabled } from 'reselect'
import { assert } from './autotrackMemoize/utils';
import { OutputSelectorFields, Mapped } from './types';
*
* // Run only the first time the selector is called. (default)
* setInputStabilityCheckEnabled('once')
*
* // Run every time the selector is called.
* setInputStabilityCheckEnabled('always')
*
* // Never run the input stability check.
* setInputStabilityCheckEnabled('never')
* ```
* @see {@link https://github.com/reduxjs/reselect#development-only-checks development-only-checks}
* @see {@link https://github.com/reduxjs/reselect#global-configuration global-configuration}
*
* @since 5.0.0
* @public
*/
export function setInputStabilityCheckEnabled(
inputStabilityCheckFrequency: StabilityCheckFrequency
) {
globalStabilityCheck = inputStabilityCheckFrequency
}
/**
* Creates a selector creator function with the specified memoization function and options for customizing memoization behavior.

@@ -222,5 +180,5 @@ *

* @template MemoizeFunction - The type of the memoize function that is used to memoize the `resultFunc` inside `createSelector` (e.g., `defaultMemoize` or `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., `defaultMemoize` or `weakMapMemoize`). If none is explicitly provided, `defaultMemoize` will be used.
* @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., `defaultMemoize` or `weakMapMemoize`). If none is explicitly provided, `weakMapMemoize` will be used.
*
* @see {@link https://github.com/reduxjs/reselect#createselectorcreatormemoize-memoizeoptions createSelectorCreator}
* @see {@link https://github.com/reduxjs/reselect#createselectorcreatormemoize--options-memoizeoptions createSelectorCreator}
*

@@ -232,9 +190,14 @@ * @since 5.0.0

MemoizeFunction extends UnknownMemoizer,
ArgsMemoizeFunction extends UnknownMemoizer = typeof defaultMemoize
ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize
>(
options: CreateSelectorOptions<
typeof defaultMemoize,
typeof defaultMemoize,
MemoizeFunction,
ArgsMemoizeFunction
options: Simplify<
SetRequired<
CreateSelectorOptions<
typeof weakMapMemoize,
typeof weakMapMemoize,
MemoizeFunction,
ArgsMemoizeFunction
>,
'memoize'
>
>

@@ -266,3 +229,3 @@ ): CreateSelectorFunction<MemoizeFunction, ArgsMemoizeFunction>

*
* @see {@link https://github.com/reduxjs/reselect#createselectorcreatormemoize-memoizeoptions createSelectorCreator}
* @see {@link https://github.com/reduxjs/reselect#createselectorcreatormemoize--options-memoizeoptions createSelectorCreator}
*

@@ -284,3 +247,3 @@ * @public

* @template MemoizeFunction - The type of the memoize function that is used to memoize the `resultFunc` inside `createSelector` (e.g., `defaultMemoize` or `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., `defaultMemoize` or `weakMapMemoize`). If none is explicitly provided, `defaultMemoize` will be used.
* @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., `defaultMemoize` or `weakMapMemoize`). If none is explicitly provided, `weakMapMemoize` will be used.
* @template MemoizeOrOptions - The type of the first argument. It can either be a `memoize` function or an `options` object containing the `memoize` function.

@@ -293,8 +256,11 @@ */

| MemoizeFunction
| CreateSelectorOptions<MemoizeFunction, ArgsMemoizeFunction>
| SetRequired<
CreateSelectorOptions<MemoizeFunction, ArgsMemoizeFunction>,
'memoize'
>
>(
memoizeOrOptions: MemoizeOrOptions,
...memoizeOptionsFromArgs: MemoizeOrOptions extends CreateSelectorOptions<
MemoizeFunction,
ArgsMemoizeFunction
...memoizeOptionsFromArgs: MemoizeOrOptions extends SetRequired<
CreateSelectorOptions<MemoizeFunction, ArgsMemoizeFunction>,
'memoize'
>

@@ -305,12 +271,11 @@ ? never

/** options initially passed into `createSelectorCreator`. */
const createSelectorCreatorOptions: CreateSelectorOptions<
MemoizeFunction,
ArgsMemoizeFunction
> =
typeof memoizeOrOptions === 'function'
? {
memoize: memoizeOrOptions as MemoizeFunction,
memoizeOptions: memoizeOptionsFromArgs
}
: memoizeOrOptions
const createSelectorCreatorOptions: SetRequired<
CreateSelectorOptions<MemoizeFunction, ArgsMemoizeFunction>,
'memoize'
> = typeof memoizeOrOptions === 'function'
? {
memoize: memoizeOrOptions as MemoizeFunction,
memoizeOptions: memoizeOptionsFromArgs
}
: memoizeOrOptions

@@ -326,9 +291,7 @@ const createSelector = <

combiner: Combiner<InputSelectors, Result>,
createSelectorOptions?: Partial<
CreateSelectorOptions<
MemoizeFunction,
ArgsMemoizeFunction,
OverrideMemoizeFunction,
OverrideArgsMemoizeFunction
>
createSelectorOptions?: CreateSelectorOptions<
MemoizeFunction,
ArgsMemoizeFunction,
OverrideMemoizeFunction,
OverrideArgsMemoizeFunction
>

@@ -338,14 +301,13 @@ ]

let recomputations = 0
let dependencyRecomputations = 0
let lastResult: Result
// Due to the intricacies of rest params, we can't do an optional arg after `...funcs`.
// Due to the intricacies of rest params, we can't do an optional arg after `...createSelectorArgs`.
// So, start by declaring the default value here.
// (And yes, the words 'memoize' and 'options' appear too many times in this next sequence.)
let directlyPassedOptions: Partial<
CreateSelectorOptions<
MemoizeFunction,
ArgsMemoizeFunction,
OverrideMemoizeFunction,
OverrideArgsMemoizeFunction
>
let directlyPassedOptions: CreateSelectorOptions<
MemoizeFunction,
ArgsMemoizeFunction,
OverrideMemoizeFunction,
OverrideArgsMemoizeFunction
> = {}

@@ -356,9 +318,7 @@

| Combiner<InputSelectors, Result>
| Partial<
CreateSelectorOptions<
MemoizeFunction,
ArgsMemoizeFunction,
OverrideMemoizeFunction,
OverrideArgsMemoizeFunction
>
| CreateSelectorOptions<
MemoizeFunction,
ArgsMemoizeFunction,
OverrideMemoizeFunction,
OverrideArgsMemoizeFunction
>

@@ -388,5 +348,5 @@

memoizeOptions = [],
argsMemoize = defaultMemoize,
argsMemoize = weakMapMemoize,
argsMemoizeOptions = [],
inputStabilityCheck = globalStabilityCheck
devModeChecks = {}
} = combinedOptions

@@ -418,2 +378,3 @@

const selector = argsMemoize(function dependenciesChecker() {
dependencyRecomputations++
/** Return values of input selectors which the `resultFunc` takes as arguments. */

@@ -425,18 +386,25 @@ const inputSelectorResults = collectInputSelectorResults(

if (
process.env.NODE_ENV !== 'production' &&
shouldRunInputStabilityCheck(inputStabilityCheck, firstRun)
) {
// make a second copy of the params, to check if we got the same results
const inputSelectorResultsCopy = collectInputSelectorResults(
dependencies,
arguments
)
if (process.env.NODE_ENV !== 'production') {
const { identityFunctionCheck, inputStabilityCheck } =
getDevModeChecksExecutionInfo(firstRun, devModeChecks)
if (identityFunctionCheck.shouldRun) {
identityFunctionCheck.run(
resultFunc as Combiner<InputSelectors, Result>
)
}
runStabilityCheck(
{ inputSelectorResults, inputSelectorResultsCopy },
{ memoize, memoizeOptions: finalMemoizeOptions },
arguments
)
if (inputStabilityCheck.shouldRun) {
// make a second copy of the params, to check if we got the same results
const inputSelectorResultsCopy = collectInputSelectorResults(
dependencies,
arguments
)
inputStabilityCheck.run(
{ inputSelectorResults, inputSelectorResultsCopy },
{ memoize, memoizeOptions: finalMemoizeOptions },
arguments
)
}
if (firstRun) firstRun = false

@@ -461,5 +429,11 @@ }

dependencies,
dependencyRecomputations: () => dependencyRecomputations,
resetDependencyRecomputations: () => {
dependencyRecomputations = 0
},
lastResult: () => lastResult,
recomputations: () => recomputations,
resetRecomputations: () => (recomputations = 0),
resetRecomputations: () => {
recomputations = 0
},
memoize,

@@ -485,3 +459,3 @@ argsMemoize

*
* @see {@link https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc-selectoroptions createSelector}
* @see {@link https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc-createselectoroptions createSelector}
*

@@ -491,2 +465,2 @@ * @public

export const createSelector =
/* #__PURE__ */ createSelectorCreator(defaultMemoize)
/* #__PURE__ */ createSelectorCreator(weakMapMemoize)

@@ -6,5 +6,7 @@ import { createSelector } from './createSelectorCreator'

import type {
InterruptRecursion,
ObjectValuesToTuple,
OutputSelector,
Selector,
Simplify,
UnknownMemoizer

@@ -63,3 +65,3 @@ } from './types'

*
* @see {@link https://github.com/reduxjs/reselect#createstructuredselectorinputselectors-selectorcreator--createselector createStructuredSelector}
* @see {@link https://github.com/reduxjs/reselect#createstructuredselector-inputselectorsobject--selectorcreator--createselector createStructuredSelector}
*

@@ -70,7 +72,6 @@ * @public

/**
* A convenience function for a common pattern that arises when using Reselect.
* The selector passed to a `connect` decorator often just takes the
* values of its input selectors and maps them to keys in an object.
* A convenience function that simplifies returning an object
* made up of selector results.
*
* @param selectorMap - A key value pair consisting of input selectors.
* @param inputSelectorsObject - A key value pair consisting of input selectors.
* @param selectorCreator - A custom selector creator function. It defaults to `createSelector`.

@@ -84,54 +85,18 @@ * @returns A memoized structured selector.

*
* interface State {
* interface RootState {
* todos: {
* id: number
* completed: boolean
* title: string
* description: string
* completed: boolean
* }[]
* alerts: {
* id: number
* message: string
* type: 'reminder' | 'notification'
* read: boolean
* }[]
* alerts: { id: number; read: boolean }[]
* }
*
* const state: State = {
* todos: [
* {
* id: 0,
* title: 'Buy groceries',
* description: 'Milk, bread, eggs, and fruits',
* completed: false
* },
* {
* id: 1,
* title: 'Schedule dentist appointment',
* description: 'Check available slots for next week',
* completed: true
* }
* ],
* alerts: [
* {
* id: 0,
* message: 'You have an upcoming meeting at 3 PM.',
* type: 'reminder',
* read: false
* },
* {
* id: 1,
* message: 'New software update available.',
* type: 'notification',
* read: true
* }
* ]
* }
*
* // This:
* const structuredSelector = createStructuredSelector(
* {
* allTodos: (state: State) => state.todos,
* allAlerts: (state: State) => state.alerts,
* selectedTodo: (state: State, id: number) => state.todos[id]
* todos: (state: RootState) => state.todos,
* alerts: (state: RootState) => state.alerts,
* todoById: (state: RootState, id: number) => state.todos[id]
* },

@@ -144,11 +109,11 @@ * createSelector

* [
* (state: State) => state.todos,
* (state: State) => state.alerts,
* (state: State, id: number) => state.todos[id]
* (state: RootState) => state.todos,
* (state: RootState) => state.alerts,
* (state: RootState, id: number) => state.todos[id]
* ],
* (allTodos, allAlerts, selectedTodo) => {
* (todos, alerts, todoById) => {
* return {
* allTodos,
* allAlerts,
* selectedTodo
* todos,
* alerts,
* todoById
* }

@@ -176,6 +141,6 @@ * }

* @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 `defaultMemoize`.
* @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 `defaultMemoize`.
* @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://github.com/reduxjs/reselect#createstructuredselectorinputselectors-selectorcreator--createselector createStructuredSelector}
* @see {@link https://github.com/reduxjs/reselect#createstructuredselector-inputselectorsobject--selectorcreator--createselector createStructuredSelector}
*/

@@ -187,3 +152,3 @@ <

>(
selectorMap: InputSelectorsObject,
inputSelectorsObject: InputSelectorsObject,
selectorCreator?: CreateSelectorFunction<

@@ -195,52 +160,56 @@ MemoizeFunction,

ObjectValuesToTuple<InputSelectorsObject>,
SelectorsMap<InputSelectorsObject>,
Simplify<SelectorsMap<InputSelectorsObject>>,
MemoizeFunction,
ArgsMemoizeFunction
>
// TODO: Do we need this?
/**
* Second overload
*/
// <
// State,
// Result = State,
// MemoizeFunction extends UnknownMemoizer = typeof defaultMemoize,
// ArgsMemoizeFunction extends UnknownMemoizer = typeof defaultMemoize
// >(
// selectors: {
// [Key in keyof State]: Selector<State, State[Key], never>
// },
// selectorCreator?: CreateSelectorFunction<
// MemoizeFunction,
// ArgsMemoizeFunction
// >
// ): OutputSelector<
// readonly Selector<State, State, []>[],
// Result,
// MemoizeFunction,
// ArgsMemoizeFunction
// >
> &
InterruptRecursion
}
// Manual definition of state and output arguments
/**
* A convenience function for a common pattern that arises when using Reselect.
* The selector passed to a `connect` decorator often just takes the values of its input selectors
* and maps them to keys in an object.
* A convenience function that simplifies returning an object
* made up of selector results.
*
* @example
* <caption>Simple Use Case</caption>
* <caption>Modern Use Case</caption>
* ```ts
* const selectA = state => state.a
* const selectB = state => state.b
* import { createSelector, createStructuredSelector } from 'reselect'
*
* // 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
* }))
* 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
* }
* }
* )
* ```
*
* @see {@link https://github.com/reduxjs/reselect#createstructuredselectorinputselectors-selectorcreator--createselector createStructuredSelector}
* @see {@link https://github.com/reduxjs/reselect#createstructuredselector-inputselectorsobject--selectorcreator--createselector createStructuredSelector}
*

@@ -247,0 +216,0 @@ * @public

@@ -1,9 +0,14 @@

import type { AnyFunction, EqualityFn } from './types'
import type {
AnyFunction,
DefaultMemoizeFields,
EqualityFn,
Simplify
} from './types'
import type { NOT_FOUND_TYPE } from './utils'
import { NOT_FOUND } from './utils'
// Cache implementation based on Erik Rasmussen's `lru-memoize`:
// https://github.com/erikras/lru-memoize
const NOT_FOUND = 'NOT_FOUND'
type NOT_FOUND_TYPE = typeof NOT_FOUND
interface Entry {

@@ -91,2 +96,5 @@ key: unknown

/**
* Runs a simple reference equality check.
* What {@linkcode defaultMemoize defaultMemoize} uses by default.
*
* @public

@@ -122,3 +130,3 @@ */

*/
export interface DefaultMemoizeOptions {
export interface DefaultMemoizeOptions<T = any> {
/**

@@ -139,3 +147,3 @@ * Used to compare the individual arguments of the provided calculation function.

*/
resultEqualityCheck?: EqualityFn
resultEqualityCheck?: EqualityFn<T>
/**

@@ -165,3 +173,3 @@ * The cache size for the selector. If greater than 1, the selector will use an LRU cache internally.

func: Func,
equalityCheckOrOptions?: EqualityFn | DefaultMemoizeOptions
equalityCheckOrOptions?: EqualityFn | DefaultMemoizeOptions<ReturnType<Func>>
) {

@@ -181,2 +189,4 @@ const providedOptions =

let resultsCount = 0
const cache =

@@ -189,6 +199,7 @@ maxSize === 1

function memoized() {
let value = cache.get(arguments)
let value = cache.get(arguments) as ReturnType<Func>
if (value === NOT_FOUND) {
// @ts-ignore
value = func.apply(null, arguments)
value = func.apply(null, arguments) as ReturnType<Func>
resultsCount++

@@ -198,7 +209,8 @@ if (resultEqualityCheck) {

const matchingEntry = entries.find(entry =>
resultEqualityCheck(entry.value, value)
resultEqualityCheck(entry.value as ReturnType<Func>, value)
)
if (matchingEntry) {
value = matchingEntry.value
value = matchingEntry.value as ReturnType<Func>
resultsCount--
}

@@ -214,5 +226,12 @@ }

cache.clear()
memoized.resetResultsCount()
}
return memoized as Func & { clearCache: () => void }
memoized.resultsCount = () => resultsCount
memoized.resetResultsCount = () => {
resultsCount = 0
}
return memoized as Func & Simplify<DefaultMemoizeFields>
}
export { autotrackMemoize as unstable_autotrackMemoize } from './autotrackMemoize/autotrackMemoize'
export {
createSelector,
createSelectorCreator,
setInputStabilityCheckEnabled
} from './createSelectorCreator'
export { createSelector, createSelectorCreator } from './createSelectorCreator'
export type { CreateSelectorFunction } from './createSelectorCreator'

@@ -15,17 +11,23 @@ export { createStructuredSelector } from './createStructuredSelector'

export type { DefaultMemoizeOptions } from './defaultMemoize'
export { setGlobalDevModeChecks } from './devModeChecks/setGlobalDevModeChecks'
export type {
Combiner,
CreateSelectorOptions,
DefaultMemoizeFields,
DevModeCheckFrequency,
DevModeChecks,
DevModeChecksExecutionInfo,
EqualityFn,
ExtractMemoizerFields,
GetParamsFromSelectors,
GetStateFromSelectors,
OutputParametricSelector,
MemoizeOptionsFromParameters,
OutputSelector,
OutputSelectorFields,
ParametricSelector,
OverrideMemoizeOptions,
Selector,
SelectorArray,
SelectorResultArray,
StabilityCheckFrequency
UnknownMemoizer
} from './types'
export { weakMapMemoize } from './weakMapMemoize'

@@ -1,3 +0,3 @@

import type { defaultMemoize } from './defaultMemoize'
import type { MergeParameters } from './versionedTypes'
import type { weakMapMemoize } from './weakMapMemoize'

@@ -58,5 +58,5 @@ export type { MergeParameters } from './versionedTypes'

* @template MemoizeFunction - The type of the memoize function that is used to memoize the `resultFunc` inside `createSelector` (e.g., `defaultMemoize` or `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., `defaultMemoize` or `weakMapMemoize`). If none is explicitly provided, `defaultMemoize` will be used.
* @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., `defaultMemoize` or `weakMapMemoize`). If none is explicitly provided, `weakMapMemoize` will be used.
* @template OverrideMemoizeFunction - The type of the optional `memoize` function that could be passed into the options object inside `createSelector` to override the original `memoize` function that was initially passed into `createSelectorCreator`.
* @template OverrideArgsMemoizeFunction - The type of the optional `argsMemoize` function that could be passed into the options object inside `createSelector` to override the original `argsMemoize` function that was initially passed into `createSelectorCreator`. If none was initially provided, `defaultMemoize` will be used.
* @template OverrideArgsMemoizeFunction - The type of the optional `argsMemoize` function that could be passed into the options object inside `createSelector` to override the original `argsMemoize` function that was initially passed into `createSelectorCreator`. If none was initially provided, `weakMapMemoize` will be used.
*

@@ -66,4 +66,4 @@ * @public

export interface CreateSelectorOptions<
MemoizeFunction extends UnknownMemoizer = typeof defaultMemoize,
ArgsMemoizeFunction extends UnknownMemoizer = typeof defaultMemoize,
MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize,
ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize,
OverrideMemoizeFunction extends UnknownMemoizer = never,

@@ -73,16 +73,11 @@ OverrideArgsMemoizeFunction extends UnknownMemoizer = never

/**
* Overrides the global input stability check for the selector.
* - `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.
* Reselect performs additional checks in development mode to help identify
* and warn about potential issues in selector behavior. This option
* allows you to customize the behavior of these checks per selector.
*
* @default 'once'
* @see {@link https://github.com/reduxjs/reselect#debugging-tools debugging-tools}
*
* @see {@link https://github.com/reduxjs/reselect#development-only-checks development-only-checks}
* @see {@link https://github.com/reduxjs/reselect#inputstabilitycheck inputStabilityCheck}
* @see {@link https://github.com/reduxjs/reselect#per-selector-configuration per-selector-configuration}
*
* @since 5.0.0
*/
inputStabilityCheck?: StabilityCheckFrequency
devModeChecks?: Partial<DevModeChecks>

@@ -99,8 +94,8 @@ /**

*
* const selectTodoById = createSelector(
* const selectItemsByCategory = createSelector(
* [
* (state: RootState) => state.todos,
* (state: RootState, id: number) => id
* (state: RootState) => state.items,
* (state: RootState, category: string) => category
* ],
* (todos) => todos[id],
* (items, category) => items.filter(item => item.category === category),
* { memoize: weakMapMemoize }

@@ -112,9 +107,12 @@ * )

*/
// If `memoize` is not provided inside the options object, fallback to `MemoizeFunction` which is the original memoize function passed into `createSelectorCreator`.
memoize: FallbackIfNever<OverrideMemoizeFunction, MemoizeFunction>
memoize?: FallbackIfNever<OverrideMemoizeFunction, MemoizeFunction>
/**
* The optional memoize function that is used to memoize the arguments passed into the output selector generated by `createSelector` (e.g., `defaultMemoize` or `weakMapMemoize`).
* The optional memoize function that is used to memoize the arguments
* passed into the output selector generated by `createSelector`
* (e.g., `defaultMemoize` or `weakMapMemoize`).
*
* When passed directly into `createSelector`, it overrides the `argsMemoize` function initially passed into `createSelectorCreator`. If none was initially provided, `defaultMemoize` will be used.
* When passed directly into `createSelector`, it overrides the
* `argsMemoize` function initially passed into `createSelectorCreator`.
* If none was initially provided, `weakMapMemoize` will be used.
*

@@ -125,8 +123,8 @@ * @example

*
* const selectTodoById = createSelector(
* const selectItemsByCategory = createSelector(
* [
* (state: RootState) => state.todos,
* (state: RootState, id: number) => id
* (state: RootState) => state.items,
* (state: RootState, category: string) => category
* ],
* (todos) => todos[id],
* (items, category) => items.filter(item => item.category === category),
* { argsMemoize: weakMapMemoize }

@@ -136,9 +134,6 @@ * )

*
* @default defaultMemoize
* @default weakMapMemoize
*
* @since 5.0.0
*/
// If `argsMemoize` is not provided inside the options object,
// fallback to `ArgsMemoizeFunction` which is the original `argsMemoize` function passed into `createSelectorCreator`.
// If none was passed originally to `createSelectorCreator`, it should fallback to `defaultMemoize`.
argsMemoize?: FallbackIfNever<

@@ -155,3 +150,2 @@ OverrideArgsMemoizeFunction,

*/
// Should dynamically change to the options argument of `memoize`.
memoizeOptions?: OverrideMemoizeOptions<

@@ -188,3 +182,3 @@ MemoizeFunction,

* @template MemoizeFunction - The type of the memoize function that is used to memoize the `resultFunc` inside `createSelector` (e.g., `defaultMemoize` or `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., `defaultMemoize` or `weakMapMemoize`). If none is explicitly provided, `defaultMemoize` will be used.
* @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., `defaultMemoize` or `weakMapMemoize`). If none is explicitly provided, `weakMapMemoize` will be used.
*

@@ -196,18 +190,54 @@ * @public

Result = unknown,
MemoizeFunction extends UnknownMemoizer = typeof defaultMemoize,
ArgsMemoizeFunction extends UnknownMemoizer = typeof defaultMemoize
MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize,
ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize
> = {
/** The final function passed to `createSelector`. Otherwise known as the `combiner`.*/
/**
* The final function passed to `createSelector`. Otherwise known as the `combiner`.
*/
resultFunc: Combiner<InputSelectors, Result>
/** The memoized version of {@linkcode OutputSelectorFields.resultFunc resultFunc}. */
/**
* The memoized version of {@linkcode OutputSelectorFields.resultFunc resultFunc}.
*/
memoizedResultFunc: Combiner<InputSelectors, Result> &
ExtractMemoizerFields<MemoizeFunction>
/** Returns the last result calculated by the output selector. */
/**
* @Returns The last result calculated by {@linkcode OutputSelectorFields.memoizedResultFunc memoizedResultFunc}.
*/
lastResult: () => Result
/** An array of the input selectors. */
/**
* The array of the input selectors used by `createSelector` to compose the
* combiner ({@linkcode OutputSelectorFields.memoizedResultFunc memoizedResultFunc}).
*/
dependencies: InputSelectors
/** Counts the number of times the output has been recalculated. */
/**
* Counts the number of times {@linkcode OutputSelectorFields.memoizedResultFunc memoizedResultFunc} has been recalculated.
*/
recomputations: () => number
/** Resets the count of `recomputations` count to 0. */
resetRecomputations: () => 0
/**
* Resets the count of {@linkcode OutputSelectorFields.recomputations recomputations} count to 0.
*/
resetRecomputations: () => void
/**
* Counts the number of times the input selectors ({@linkcode OutputSelectorFields.dependencies dependencies})
* have been recalculated. This is distinct from {@linkcode OutputSelectorFields.recomputations recomputations},
* which tracks the recalculations of the result function.
*
* @since 5.0.0
*/
dependencyRecomputations: () => number
/**
* Resets the count {@linkcode OutputSelectorFields.dependencyRecomputations dependencyRecomputations}
* for the input selectors ({@linkcode OutputSelectorFields.dependencies dependencies})
* of a memoized selector.
*
* @since 5.0.0
*/
resetDependencyRecomputations: () => void
} & Simplify<

@@ -228,3 +258,3 @@ Required<

* @template MemoizeFunction - The type of the memoize function that is used to memoize the `resultFunc` inside `createSelector` (e.g., `defaultMemoize` or `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., `defaultMemoize` or `weakMapMemoize`). If none is explicitly provided, `defaultMemoize` will be used.
* @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., `defaultMemoize` or `weakMapMemoize`). If none is explicitly provided, `weakMapMemoize` will be used.
*

@@ -236,4 +266,4 @@ * @public

Result = unknown,
MemoizeFunction extends UnknownMemoizer = typeof defaultMemoize,
ArgsMemoizeFunction extends UnknownMemoizer = typeof defaultMemoize
MemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize,
ArgsMemoizeFunction extends UnknownMemoizer = typeof weakMapMemoize
> = Selector<

@@ -271,40 +301,76 @@ GetStateFromSelectors<InputSelectors>,

/**
* A selector that is assumed to have one additional argument, such as
* the props from a React component.
* A standard function returning true if two values are considered equal.
*
* @public
*/
export type ParametricSelector<State, Props, Result> = Selector<
State,
Result,
[Props, ...any]
>
export type EqualityFn<T = any> = (a: T, b: T) => boolean
/**
* A generated selector that is assumed to have one additional argument.
* The frequency of development mode checks.
*
* @since 5.0.0
* @public
*/
export type OutputParametricSelector<State, Props, Result> = ParametricSelector<
State,
Props,
Result
> &
OutputSelectorFields<SelectorArray, Result>
export type DevModeCheckFrequency = 'always' | 'once' | 'never'
/**
* A standard function returning true if two values are considered equal.
* Represents the configuration for development mode checks.
*
* @since 5.0.0
* @public
*/
export type EqualityFn = (a: any, b: any) => boolean
export interface DevModeChecks {
/**
* Overrides the global input stability check for the selector.
* - `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'
*
* @see {@link https://github.com/reduxjs/reselect#debugging-tools debugging-tools}
* @see {@link https://github.com/reduxjs/reselect#inputstabilitycheck inputStabilityCheck}
* @see {@link https://github.com/reduxjs/reselect#2-per-selector-by-passing-an-inputstabilitycheck-option-directly-to-createselector per-selector-configuration}
*
* @since 5.0.0
*/
inputStabilityCheck: DevModeCheckFrequency
/**
* Overrides the global identity function check for the selector.
* - `once` - Run only the first time the selector is called.
* - `always` - Run every time the selector is called.
* - `never` - Never run the identity function check.
*
* @default 'once'
*
* @see {@link https://github.com/reduxjs/reselect#debugging-tools debugging-tools}
* @see {@link https://github.com/reduxjs/reselect#identityfunctioncheck identityFunctionCheck}
* @see {@link https://github.com/reduxjs/reselect#2-per-selector-by-passing-an-identityfunctioncheck-option-directly-to-createselector per-selector-configuration}
*
* @since 5.0.0
*/
identityFunctionCheck: DevModeCheckFrequency
}
/**
* The frequency of input stability checks.
* Represents execution information for development mode checks.
*
* @public
* @since 5.0.0
* @public
*/
export type StabilityCheckFrequency = 'always' | 'once' | 'never'
export type DevModeChecksExecutionInfo = {
[K in keyof DevModeChecks]: {
/**
* A boolean indicating whether the check should be executed.
*/
shouldRun: boolean
/**
* The function to execute for the check.
*/
run: AnyFunction
}
}
/**

@@ -327,27 +393,3 @@ * Determines the combined single "State" type (first arg) from all input selectors.

/*
* -----------------------------------------------------------------------------
* -----------------------------------------------------------------------------
*
* Reselect Internal Utility Types
*
* -----------------------------------------------------------------------------
* -----------------------------------------------------------------------------
*/
/**
* Any function with any arguments.
*
* @internal
*/
export type AnyFunction = (...args: any[]) => any
/**
* Any function with unknown arguments.
*
* @internal
*/
export type UnknownFunction = (...args: unknown[]) => unknown
/**
* Any Memoizer function. A memoizer is a function that accepts another function and returns it.

@@ -357,3 +399,3 @@ *

*
* @internal
* @public
*/

@@ -365,10 +407,21 @@ export type UnknownMemoizer<

/**
* When a generic type parameter is using its default value of `never`, fallback to a different type.
* Extracts the options type for a memoization function based on its parameters.
* The first parameter of the function is expected to be the function to be memoized,
* followed by options for the memoization process.
*
* @template T - Type to be checked.
* @template FallbackTo - Type to fallback to if `T` resolves to `never`.
* @template MemoizeFunction - The type of the memoize function to be checked.
*
* @internal
* @public
*/
export type FallbackIfNever<T, FallbackTo> = IfNever<T, FallbackTo, T>
export type MemoizeOptionsFromParameters<
MemoizeFunction extends UnknownMemoizer
> =
| (
| NonFunctionType<DropFirstParameter<MemoizeFunction>[0]>
| FunctionType<DropFirstParameter<MemoizeFunction>[0]>
)
| (
| NonFunctionType<DropFirstParameter<MemoizeFunction>[number]>
| FunctionType<DropFirstParameter<MemoizeFunction>[number]>
)[]

@@ -383,3 +436,3 @@ /**

*
* @internal
* @public
*/

@@ -391,55 +444,91 @@ export type OverrideMemoizeOptions<

OverrideMemoizeFunction,
MemoizeOptionsFromParameters<MemoizeFunction>,
MemoizeOptionsFromParameters<OverrideMemoizeFunction>
Simplify<MemoizeOptionsFromParameters<MemoizeFunction>>,
Simplify<MemoizeOptionsFromParameters<OverrideMemoizeFunction>>
>
/**
* Extracts the non-function part of a type.
* Extracts the additional properties or methods that a memoize function attaches to
* the function it memoizes (e.g., `clearCache`).
*
* @template T - The input type to be refined by excluding function types and index signatures.
* @template MemoizeFunction - The type of the memoize function to be checked.
*
* @public
*/
export type ExtractMemoizerFields<MemoizeFunction extends UnknownMemoizer> =
Simplify<OmitIndexSignature<ReturnType<MemoizeFunction>>>
/**
* Represents the additional properties attached to a function memoized by `reselect`.
*
* `defaultMemoize`, `weakMapMemoize` and `autotrackMemoize` all return these properties.
*
* @see {@linkcode ExtractMemoizerFields ExtractMemoizerFields}
*
* @public
*/
export type DefaultMemoizeFields = {
/**
* Clears the memoization cache associated with a memoized function.
* This method is typically used to reset the state of the cache, allowing
* for the garbage collection of previously memoized results and ensuring
* that future calls to the function recompute the results.
*/
clearCache: () => void
resultsCount: () => number
resetResultsCount: () => void
}
/*
* -----------------------------------------------------------------------------
* -----------------------------------------------------------------------------
*
* Reselect Internal Utility Types
*
* -----------------------------------------------------------------------------
* -----------------------------------------------------------------------------
*/
/**
* Any function with any arguments.
*
* @internal
*/
export type NonFunctionType<T> = OmitIndexSignature<Exclude<T, AnyFunction>>
export type AnyFunction = (...args: any[]) => any
/**
* Extracts the function part of a type.
* Any function with unknown arguments.
*
* @template T - The input type to be refined by extracting function types.
* @internal
*/
export type UnknownFunction = (...args: unknown[]) => unknown
/**
* When a generic type parameter is using its default value of `never`, fallback to a different type.
*
* @template T - Type to be checked.
* @template FallbackTo - Type to fallback to if `T` resolves to `never`.
*
* @internal
*/
export type FunctionType<T> = Extract<T, AnyFunction>
export type FallbackIfNever<T, FallbackTo> = IfNever<T, FallbackTo, T>
/**
* Extracts the options type for a memoization function based on its parameters.
* The first parameter of the function is expected to be the function to be memoized,
* followed by options for the memoization process.
* Extracts the non-function part of a type.
*
* @template MemoizeFunction - The type of the memoize function to be checked.
* @template T - The input type to be refined by excluding function types and index signatures.
*
* @internal
*/
export type MemoizeOptionsFromParameters<
MemoizeFunction extends UnknownMemoizer
> =
| (
| Simplify<NonFunctionType<DropFirstParameter<MemoizeFunction>[0]>>
| FunctionType<DropFirstParameter<MemoizeFunction>[0]>
)
| (
| Simplify<NonFunctionType<DropFirstParameter<MemoizeFunction>[number]>>
| FunctionType<DropFirstParameter<MemoizeFunction>[number]>
)[]
export type NonFunctionType<T> = Simplify<
OmitIndexSignature<Exclude<T, AnyFunction>>
>
/**
* Extracts the additional fields that a memoize function attaches to
* the function it memoizes (e.g., `clearCache`).
* Extracts the function part of a type.
*
* @template MemoizeFunction - The type of the memoize function to be checked.
* @template T - The input type to be refined by extracting function types.
*
* @internal
*/
export type ExtractMemoizerFields<MemoizeFunction extends UnknownMemoizer> =
Simplify<OmitIndexSignature<ReturnType<MemoizeFunction>>>
export type FunctionType<T> = Extract<T, AnyFunction>

@@ -453,3 +542,3 @@ /**

[Index in keyof FunctionsArray]: FunctionsArray[Index] extends FunctionsArray[number]
? ReturnType<FunctionsArray[Index]>
? FallbackIfUnknown<ReturnType<FunctionsArray[Index]>, any>
: never

@@ -488,7 +577,7 @@ }

*/
export type FirstArrayElement<TArray> = TArray extends readonly [
export type FirstArrayElement<ArrayType> = ArrayType extends readonly [
unknown,
...unknown[]
]
? TArray[0]
? ArrayType[0]
: never

@@ -501,7 +590,7 @@

*/
export type ArrayTail<TArray> = TArray extends readonly [
export type ArrayTail<ArrayType> = ArrayType extends readonly [
unknown,
...infer TTail
...infer Tail
]
? TTail
? Tail
: []

@@ -588,3 +677,4 @@

(mergedIntersection: infer Intersection) => void
? Intersection
? // The `& Union` is to allow indexing by the resulting type
Intersection & Union
: never

@@ -638,3 +728,39 @@

/**
* Create a type that makes the given keys required.
* The remaining keys are kept as is.
*
* @see {@link https://github.com/sindresorhus/type-fest/blob/main/source/set-required.d.ts Source}
*
* @internal
*/
export type SetRequired<BaseType, Keys extends keyof BaseType> = Omit<
BaseType,
Keys
> &
Required<Pick<BaseType, Keys>>
/**
* An if-else-like type that resolves depending on whether the given type is `unknown`.
* @see {@link https://github.com/sindresorhus/type-fest/blob/main/source/if-unknown.d.ts Source}
*
* @internal
*/
export type IfUnknown<T, TypeIfUnknown, TypeIfNotUnknown> = unknown extends T // `T` can be `unknown` or `any`
? [T] extends [null] // `any` can be `null`, but `unknown` can't be
? TypeIfNotUnknown
: TypeIfUnknown
: TypeIfNotUnknown
/**
* When a type is resolves to `unknown`, fallback to a different type.
*
* @template T - Type to be checked.
* @template FallbackTo - Type to fallback to if `T` resolves to `unknown`.
*
* @internal
*/
export type FallbackIfUnknown<T, FallbackTo> = IfUnknown<T, FallbackTo, T>
/**
*
* -----------------------------------------------------------------------------

@@ -743,5 +869,7 @@ * -----------------------------------------------------------------------------

*/
export type Simplify<T> = {
[KeyType in keyof T]: T[KeyType]
} & AnyNonNullishValue
export type Simplify<T> = T extends AnyFunction
? T
: {
[KeyType in keyof T]: T[KeyType]
} & AnyNonNullishValue

@@ -748,0 +876,0 @@ /**

@@ -0,9 +1,15 @@

import { runIdentityFunctionCheck } from './devModeChecks/identityFunctionCheck'
import { runInputStabilityCheck } from './devModeChecks/inputStabilityCheck'
import { globalDevModeChecks } from './devModeChecks/setGlobalDevModeChecks'
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
import type {
CreateSelectorOptions,
DevModeChecks,
Selector,
SelectorArray,
StabilityCheckFrequency,
UnknownMemoizer
DevModeChecksExecutionInfo
} from './types'
export const NOT_FOUND = 'NOT_FOUND'
export type NOT_FOUND_TYPE = typeof NOT_FOUND
/**

@@ -76,3 +82,3 @@ * Assert that the provided value is a function. If the assertion fails,

*/
export const ensureIsArray = <T>(item: T | T[]) => {
export const ensureIsArray = (item: unknown) => {
return Array.isArray(item) ? item : [item]

@@ -123,62 +129,30 @@ }

/**
* Run a stability check to ensure the input selector results remain stable
* when provided with the same arguments. This function is designed to detect
* changes in the output of input selectors, which can impact the performance of memoized selectors.
* Retrieves execution information for development mode checks.
*
* @param inputSelectorResultsObject - An object containing two arrays: `inputSelectorResults` and `inputSelectorResultsCopy`, representing the results of input selectors.
* @param options - Options object consisting of a `memoize` function and a `memoizeOptions` object.
* @param inputSelectorArgs - List of arguments being passed to the input selectors.
*/
export function runStabilityCheck(
inputSelectorResultsObject: {
inputSelectorResults: unknown[]
inputSelectorResultsCopy: unknown[]
},
options: Required<
Pick<
CreateSelectorOptions<UnknownMemoizer, UnknownMemoizer>,
'memoize' | 'memoizeOptions'
>
>,
inputSelectorArgs: unknown[] | IArguments
) {
const { memoize, memoizeOptions } = options
const { inputSelectorResults, inputSelectorResultsCopy } =
inputSelectorResultsObject
const createAnEmptyObject = memoize(() => ({}), ...memoizeOptions)
// if the memoize method thinks the parameters are equal, these *should* be the same reference
const areInputSelectorResultsEqual =
createAnEmptyObject.apply(null, inputSelectorResults) ===
createAnEmptyObject.apply(null, inputSelectorResultsCopy)
if (!areInputSelectorResultsEqual) {
// do we want to log more information about the selector?
console.warn(
'An input selector returned a different result when passed same arguments.' +
'\nThis means your output selector will likely run more frequently than intended.' +
'\nAvoid returning a new reference inside your input selector, e.g.' +
'\n`createSelector([(arg1, arg2) => ({ arg1, arg2 })],(arg1, arg2) => {})`',
{
arguments: inputSelectorArgs,
firstInputs: inputSelectorResults,
secondInputs: inputSelectorResultsCopy
}
)
}
}
/**
* Determines if the input stability check should run.
*
* @param inputStabilityCheck - The frequency of the input stability check.
* @param devModeChecks - Custom Settings for development mode checks. These settings will override the global defaults.
* @param firstRun - Indicates whether it is the first time the selector has run.
* @returns true if the input stability check should run, otherwise false.
* @returns An object containing the execution information for each development mode check.
*/
export const shouldRunInputStabilityCheck = (
inputStabilityCheck: StabilityCheckFrequency,
firstRun: boolean
export const getDevModeChecksExecutionInfo = (
firstRun: boolean,
devModeChecks: Partial<DevModeChecks>
) => {
return (
inputStabilityCheck === 'always' ||
(inputStabilityCheck === 'once' && firstRun)
)
const { identityFunctionCheck, inputStabilityCheck } = {
...globalDevModeChecks,
...devModeChecks
}
return {
identityFunctionCheck: {
shouldRun:
identityFunctionCheck === 'always' ||
(identityFunctionCheck === 'once' && firstRun),
run: runIdentityFunctionCheck
},
inputStabilityCheck: {
shouldRun:
inputStabilityCheck === 'always' ||
(inputStabilityCheck === 'once' && firstRun),
run: runInputStabilityCheck
}
} satisfies DevModeChecksExecutionInfo
}
// This entire implementation courtesy of Anders Hjelsberg:
// https://github.com/microsoft/TypeScript/pull/50831#issuecomment-1253830522
import type { AnyFunction } from '@internal/types'
import type { AnyFunction } from '../types'
/**
* Represents the longest array within an array of arrays.
*
* @template ArrayOfTuples An array of arrays.
*
* @internal
*/
type LongestTuple<T extends readonly unknown[][]> = T extends [
infer U extends unknown[]
]
? U
: T extends [infer U, ...infer R extends unknown[][]]
? MostProperties<U, LongestTuple<R>>
: never
type LongestTuple<ArrayOfTuples extends readonly unknown[][]> =
ArrayOfTuples extends [infer FirstArray extends unknown[]]
? FirstArray
: ArrayOfTuples extends [
infer FirstArray,
...infer RestArrays extends unknown[][]
]
? LongerOfTwo<FirstArray, LongestTuple<RestArrays>>
: never
/**
* Determines the longer of two array types.
*
* @template ArrayOne First array type.
* @template ArrayTwo Second array type.
*
* @internal
*/
type MostProperties<T, U> = keyof U extends keyof T ? T : U
type LongerOfTwo<ArrayOne, ArrayTwo> = keyof ArrayTwo extends keyof ArrayOne
? ArrayOne
: ArrayTwo
/**
* Extracts the element at a specific index in an array.
*
* @template ArrayType The array type.
* @template Index The index type.
*
* @internal
*/
type ElementAt<T extends unknown[], N extends keyof any> = N extends keyof T
? T[N]
: unknown
type ElementAt<
ArrayType extends unknown[],
Index extends PropertyKey
> = Index extends keyof ArrayType ? ArrayType[Index] : unknown
/**
* Maps each array in an array of arrays to its element at a given index.
*
* @template ArrayOfTuples An array of arrays.
* @template Index The index to extract from each array.
*
* @internal
*/
type ElementsAt<T extends readonly unknown[][], N extends keyof any> = {
[K in keyof T]: ElementAt<T[K], N>
type ElementsAtGivenIndex<
ArrayOfTuples extends readonly unknown[][],
Index extends PropertyKey
> = {
[ArrayIndex in keyof ArrayOfTuples]: ElementAt<
ArrayOfTuples[ArrayIndex],
Index
>
}
/**
* Computes the intersection of all types in a tuple.
*
* @template Tuple A tuple of types.
*
* @internal
*/
type Intersect<T extends readonly unknown[]> = T extends []
type Intersect<Tuple extends readonly unknown[]> = Tuple extends []
? unknown
: T extends [infer H, ...infer T]
? H & Intersect<T>
: T[number]
: Tuple extends [infer Head, ...infer Tail]
? Head & Intersect<Tail>
: Tuple[number]
/**
* Merges a tuple of arrays into a single tuple, intersecting types at each index.
*
* @template ArrayOfTuples An array of tuples.
* @template LongestArray The longest array in ArrayOfTuples.
*
* @internal
*/
type MergeTuples<
T extends readonly unknown[][],
L extends unknown[] = LongestTuple<T>
ArrayOfTuples extends readonly unknown[][],
LongestArray extends unknown[] = LongestTuple<ArrayOfTuples>
> = {
[K in keyof L]: Intersect<ElementsAt<T, K>>
[Index in keyof LongestArray]: Intersect<
ElementsAtGivenIndex<ArrayOfTuples, Index>
>
}
/**
* Extracts the parameter types from a tuple of functions.
*
* @template FunctionsArray An array of function types.
*
* @internal
*/
type ExtractParameters<T extends readonly AnyFunction[]> = {
[K in keyof T]: Parameters<T[K]>
type ExtractParameters<FunctionsArray extends readonly AnyFunction[]> = {
[Index in keyof FunctionsArray]: Parameters<FunctionsArray[Index]>
}
/**
* Merges the parameters of a tuple of functions into a single tuple.
*
* @template FunctionsArray An array of function types.
*
* @internal
*/
export type MergeParameters<T extends readonly AnyFunction[]> =
'0' extends keyof T
? MergeTuples<ExtractParameters<T>>
: Parameters<T[number]>
export type MergeParameters<FunctionsArray extends readonly AnyFunction[]> =
'0' extends keyof FunctionsArray
? MergeTuples<ExtractParameters<FunctionsArray>>
: Parameters<FunctionsArray[number]>
// Original source:
// - https://github.com/facebook/react/blob/0b974418c9a56f6c560298560265dcf4b65784bc/packages/react/src/ReactCache.js
import type { AnyFunction } from './types'
import type {
AnyFunction,
DefaultMemoizeFields,
EqualityFn,
Simplify
} from './types'
class StrongRef<T> {
constructor(private value: T) {}
deref() {
return this.value
}
}
const Ref = WeakRef ?? StrongRef
const UNTERMINATED = 0

@@ -10,5 +24,17 @@ const TERMINATED = 1

interface UnterminatedCacheNode<T> {
/**
* Status, represents whether the cached computation returned a value or threw an error.
*/
s: 0
/**
* Value, either the cached result or an error, depending on status.
*/
v: void
/**
* Object cache, a `WeakMap` where non-primitive arguments are stored.
*/
o: null | WeakMap<Function | Object, CacheNode<T>>
/**
* Primitive cache, a regular Map where primitive arguments are stored.
*/
p: null | Map<string | number | null | void | symbol | boolean, CacheNode<T>>

@@ -18,5 +44,17 @@ }

interface TerminatedCacheNode<T> {
/**
* Status, represents whether the cached computation returned a value or threw an error.
*/
s: 1
/**
* Value, either the cached result or an error, depending on status.
*/
v: T
/**
* Object cache, a `WeakMap` where non-primitive arguments are stored.
*/
o: null | WeakMap<Function | Object, CacheNode<T>>
/**
* Primitive cache, a regular `Map` where primitive arguments are stored.
*/
p: null | Map<string | number | null | void | symbol | boolean, CacheNode<T>>

@@ -29,6 +67,6 @@ }

return {
s: UNTERMINATED, // status, represents whether the cached computation returned a value or threw an error
v: undefined, // value, either the cached result or an error, depending on s
o: null, // object cache, a WeakMap where non-primitive arguments are stored
p: null // primitive cache, a regular Map where primitive arguments are stored.
s: UNTERMINATED,
v: undefined,
o: null,
p: null
}

@@ -38,9 +76,25 @@ }

/**
* @public
*/
export interface WeakMapMemoizeOptions<T = any> {
/**
* If provided, used to compare a newly generated output value against previous values in the cache.
* If a match is found, the old value is returned. This addresses the common
* ```ts
* todos.map(todo => todo.id)
* ```
* use case, where an update to another field in the original data causes a recalculation
* due to changed references, but the output is still effectively the same.
*/
resultEqualityCheck?: EqualityFn<T>
}
/**
* Creates a tree of `WeakMap`-based cache nodes based on the identity of the
* arguments it's been called with (in this case, the extracted values from your input selectors).
* This allows `weakmapMemoize` to have an effectively infinite cache size.
* This allows `weakMapMemoize` to have an effectively infinite cache size.
* Cache results will be kept in memory as long as references to the arguments still exist,
* and then cleared out as the arguments are garbage-collected.
*
* __Design Tradeoffs for `weakmapMemoize`:__
* __Design Tradeoffs for `weakMapMemoize`:__
* - Pros:

@@ -54,3 +108,3 @@ * - It has an effectively infinite cache size, but you have no control over

*
* __Use Cases for `weakmapMemoize`:__
* __Use Cases for `weakMapMemoize`:__
* - This memoizer is likely best used for cases where you need to call the

@@ -71,9 +125,16 @@ * same selector instance with many different arguments, such as a single

*
* const selectTodoById = createSelector(
* interface RootState {
* items: { id: number; category: string; name: string }[]
* }
*
* const selectItemsByCategory = createSelector(
* [
* (state: RootState) => state.todos,
* (state: RootState, id: number) => id
* (state: RootState) => state.items,
* (state: RootState, category: string) => category
* ],
* (todos) => todos[id],
* { memoize: weakMapMemoize }
* (items, category) => items.filter(item => item.category === category),
* {
* memoize: weakMapMemoize,
* argsMemoize: weakMapMemoize
* }
* )

@@ -87,10 +148,10 @@ * ```

*
* const createSelectorWeakmap = createSelectorCreator(weakMapMemoize)
* const createSelectorWeakMap = createSelectorCreator({ memoize: weakMapMemoize, argsMemoize: weakMapMemoize })
*
* const selectTodoById = createSelectorWeakmap(
* const selectItemsByCategory = createSelectorWeakMap(
* [
* (state: RootState) => state.todos,
* (state: RootState, id: number) => id
* (state: RootState) => state.items,
* (state: RootState, category: string) => category
* ],
* (todos) => todos[id]
* (items, category) => items.filter(item => item.category === category)
* )

@@ -101,2 +162,4 @@ * ```

*
* @see {@link https://github.com/reduxjs/reselect#weakmapmemoizefunc---since-500 weakMapMemoize}
*
* @since 5.0.0

@@ -106,11 +169,17 @@ * @public

*/
export function weakMapMemoize<Func extends AnyFunction>(func: Func) {
// we reference arguments instead of spreading them for performance reasons
export function weakMapMemoize<Func extends AnyFunction>(
func: Func,
options: WeakMapMemoizeOptions<ReturnType<Func>> = {}
) {
let fnNode = createCacheNode()
const { resultEqualityCheck } = options
let lastResult: WeakRef<object> | undefined
let resultsCount = 0
function memoized() {
let cacheNode = fnNode
for (let i = 0, l = arguments.length; i < l; i++) {
const { length } = arguments
for (let i = 0, l = length; i < l; i++) {
const arg = arguments[i]

@@ -148,9 +217,32 @@ if (

}
const terminatedNode = cacheNode as unknown as TerminatedCacheNode<any>
let result
if (cacheNode.s === TERMINATED) {
return cacheNode.v
result = cacheNode.v
} else {
// Allow errors to propagate
result = func.apply(null, arguments as unknown as any[])
resultsCount++
}
// Allow errors to propagate
const result = func.apply(null, arguments as unknown as any[])
const terminatedNode = cacheNode as unknown as TerminatedCacheNode<any>
terminatedNode.s = TERMINATED
if (resultEqualityCheck) {
const lastResultValue = lastResult?.deref() ?? lastResult
if (
lastResultValue != null &&
resultEqualityCheck(lastResultValue as ReturnType<Func>, result)
) {
result = lastResultValue
resultsCount !== 0 && resultsCount--
}
const needsWeakRef =
(typeof result === 'object' && result !== null) ||
typeof result === 'function'
lastResult = needsWeakRef ? new Ref(result) : result
}
terminatedNode.v = result

@@ -162,5 +254,12 @@ return result

fnNode = createCacheNode()
memoized.resetResultsCount()
}
return memoized as Func & { clearCache: () => void }
memoized.resultsCount = () => resultsCount
memoized.resetResultsCount = () => {
resultsCount = 0
}
return memoized as Func & Simplify<DefaultMemoizeFields>
}

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 too big to display

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