This commit is contained in:
171
node_modules/reselect/src/defaultMemoize.ts
generated
vendored
Normal file
171
node_modules/reselect/src/defaultMemoize.ts
generated
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
import type { EqualityFn } from './types'
|
||||
|
||||
// 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 {
|
||||
key: unknown
|
||||
value: unknown
|
||||
}
|
||||
|
||||
interface Cache {
|
||||
get(key: unknown): unknown | NOT_FOUND_TYPE
|
||||
put(key: unknown, value: unknown): void
|
||||
getEntries(): Entry[]
|
||||
clear(): void
|
||||
}
|
||||
|
||||
function createSingletonCache(equals: EqualityFn): Cache {
|
||||
let entry: Entry | undefined
|
||||
return {
|
||||
get(key: unknown) {
|
||||
if (entry && equals(entry.key, key)) {
|
||||
return entry.value
|
||||
}
|
||||
|
||||
return NOT_FOUND
|
||||
},
|
||||
|
||||
put(key: unknown, value: unknown) {
|
||||
entry = { key, value }
|
||||
},
|
||||
|
||||
getEntries() {
|
||||
return entry ? [entry] : []
|
||||
},
|
||||
|
||||
clear() {
|
||||
entry = undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createLruCache(maxSize: number, equals: EqualityFn): Cache {
|
||||
let entries: Entry[] = []
|
||||
|
||||
function get(key: unknown) {
|
||||
const cacheIndex = entries.findIndex(entry => equals(key, entry.key))
|
||||
|
||||
// We found a cached entry
|
||||
if (cacheIndex > -1) {
|
||||
const entry = entries[cacheIndex]
|
||||
|
||||
// Cached entry not at top of cache, move it to the top
|
||||
if (cacheIndex > 0) {
|
||||
entries.splice(cacheIndex, 1)
|
||||
entries.unshift(entry)
|
||||
}
|
||||
|
||||
return entry.value
|
||||
}
|
||||
|
||||
// No entry found in cache, return sentinel
|
||||
return NOT_FOUND
|
||||
}
|
||||
|
||||
function put(key: unknown, value: unknown) {
|
||||
if (get(key) === NOT_FOUND) {
|
||||
// TODO Is unshift slow?
|
||||
entries.unshift({ key, value })
|
||||
if (entries.length > maxSize) {
|
||||
entries.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getEntries() {
|
||||
return entries
|
||||
}
|
||||
|
||||
function clear() {
|
||||
entries = []
|
||||
}
|
||||
|
||||
return { get, put, getEntries, clear }
|
||||
}
|
||||
|
||||
export const defaultEqualityCheck: EqualityFn = (a, b): boolean => {
|
||||
return a === b
|
||||
}
|
||||
|
||||
export function createCacheKeyComparator(equalityCheck: EqualityFn) {
|
||||
return function areArgumentsShallowlyEqual(
|
||||
prev: unknown[] | IArguments | null,
|
||||
next: unknown[] | IArguments | null
|
||||
): boolean {
|
||||
if (prev === null || next === null || prev.length !== next.length) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Do this in a for loop (and not a `forEach` or an `every`) so we can determine equality as fast as possible.
|
||||
const length = prev.length
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (!equalityCheck(prev[i], next[i])) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
export interface DefaultMemoizeOptions {
|
||||
equalityCheck?: EqualityFn
|
||||
resultEqualityCheck?: EqualityFn
|
||||
maxSize?: number
|
||||
}
|
||||
|
||||
// defaultMemoize now supports a configurable cache size with LRU behavior,
|
||||
// and optional comparison of the result value with existing values
|
||||
export function defaultMemoize<F extends (...args: any[]) => any>(
|
||||
func: F,
|
||||
equalityCheckOrOptions?: EqualityFn | DefaultMemoizeOptions
|
||||
) {
|
||||
const providedOptions =
|
||||
typeof equalityCheckOrOptions === 'object'
|
||||
? equalityCheckOrOptions
|
||||
: { equalityCheck: equalityCheckOrOptions }
|
||||
|
||||
const {
|
||||
equalityCheck = defaultEqualityCheck,
|
||||
maxSize = 1,
|
||||
resultEqualityCheck
|
||||
} = providedOptions
|
||||
|
||||
const comparator = createCacheKeyComparator(equalityCheck)
|
||||
|
||||
const cache =
|
||||
maxSize === 1
|
||||
? createSingletonCache(comparator)
|
||||
: createLruCache(maxSize, comparator)
|
||||
|
||||
// we reference arguments instead of spreading them for performance reasons
|
||||
function memoized() {
|
||||
let value = cache.get(arguments)
|
||||
if (value === NOT_FOUND) {
|
||||
// @ts-ignore
|
||||
value = func.apply(null, arguments)
|
||||
|
||||
if (resultEqualityCheck) {
|
||||
const entries = cache.getEntries()
|
||||
const matchingEntry = entries.find(entry =>
|
||||
resultEqualityCheck(entry.value, value)
|
||||
)
|
||||
|
||||
if (matchingEntry) {
|
||||
value = matchingEntry.value
|
||||
}
|
||||
}
|
||||
|
||||
cache.put(arguments, value)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
memoized.clearCache = () => cache.clear()
|
||||
|
||||
return memoized as F & { clearCache: () => void }
|
||||
}
|
||||
268
node_modules/reselect/src/index.ts
generated
vendored
Normal file
268
node_modules/reselect/src/index.ts
generated
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
import type {
|
||||
Selector,
|
||||
GetParamsFromSelectors,
|
||||
OutputSelector,
|
||||
SelectorArray,
|
||||
SelectorResultArray,
|
||||
DropFirst,
|
||||
MergeParameters,
|
||||
Expand,
|
||||
ObjValueTuple,
|
||||
Head,
|
||||
Tail
|
||||
} from './types'
|
||||
|
||||
export type {
|
||||
Selector,
|
||||
GetParamsFromSelectors,
|
||||
GetStateFromSelectors,
|
||||
OutputSelector,
|
||||
EqualityFn,
|
||||
SelectorArray,
|
||||
SelectorResultArray,
|
||||
ParametricSelector,
|
||||
OutputParametricSelector,
|
||||
OutputSelectorFields
|
||||
} from './types'
|
||||
|
||||
import {
|
||||
defaultMemoize,
|
||||
defaultEqualityCheck,
|
||||
DefaultMemoizeOptions
|
||||
} from './defaultMemoize'
|
||||
|
||||
export { defaultMemoize, defaultEqualityCheck }
|
||||
|
||||
export type { DefaultMemoizeOptions }
|
||||
|
||||
function getDependencies(funcs: unknown[]) {
|
||||
const dependencies = Array.isArray(funcs[0]) ? funcs[0] : funcs
|
||||
|
||||
if (!dependencies.every(dep => typeof dep === 'function')) {
|
||||
const dependencyTypes = dependencies
|
||||
.map(dep =>
|
||||
typeof dep === 'function'
|
||||
? `function ${dep.name || 'unnamed'}()`
|
||||
: typeof dep
|
||||
)
|
||||
.join(', ')
|
||||
|
||||
throw new Error(
|
||||
`createSelector expects all input-selectors to be functions, but received the following types: [${dependencyTypes}]`
|
||||
)
|
||||
}
|
||||
|
||||
return dependencies as SelectorArray
|
||||
}
|
||||
|
||||
export function createSelectorCreator<
|
||||
/** Selectors will eventually accept some function to be memoized */
|
||||
F extends (...args: unknown[]) => unknown,
|
||||
/** A memoizer such as defaultMemoize that accepts a function + some possible options */
|
||||
MemoizeFunction extends (func: F, ...options: any[]) => F,
|
||||
/** The additional options arguments to the memoizer */
|
||||
MemoizeOptions extends unknown[] = DropFirst<Parameters<MemoizeFunction>>
|
||||
>(
|
||||
memoize: MemoizeFunction,
|
||||
...memoizeOptionsFromArgs: DropFirst<Parameters<MemoizeFunction>>
|
||||
) {
|
||||
const createSelector = (...funcs: Function[]) => {
|
||||
let recomputations = 0
|
||||
let lastResult: unknown
|
||||
|
||||
// Due to the intricacies of rest params, we can't do an optional arg after `...funcs`.
|
||||
// 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: CreateSelectorOptions<MemoizeOptions> = {
|
||||
memoizeOptions: undefined
|
||||
}
|
||||
|
||||
// Normally, the result func or "output selector" is the last arg
|
||||
let resultFunc = funcs.pop()
|
||||
|
||||
// If the result func is actually an _object_, assume it's our options object
|
||||
if (typeof resultFunc === 'object') {
|
||||
directlyPassedOptions = resultFunc as any
|
||||
// and pop the real result func off
|
||||
resultFunc = funcs.pop()
|
||||
}
|
||||
|
||||
if (typeof resultFunc !== 'function') {
|
||||
throw new Error(
|
||||
`createSelector expects an output function after the inputs, but received: [${typeof resultFunc}]`
|
||||
)
|
||||
}
|
||||
|
||||
// Determine which set of options we're using. Prefer options passed directly,
|
||||
// but fall back to options given to createSelectorCreator.
|
||||
const { memoizeOptions = memoizeOptionsFromArgs } = directlyPassedOptions
|
||||
|
||||
// Simplifying assumption: it's unlikely that the first options arg of the provided memoizer
|
||||
// is an array. In most libs I've looked at, it's an equality function or options object.
|
||||
// Based on that, if `memoizeOptions` _is_ an array, we assume it's a full
|
||||
// user-provided array of options. Otherwise, it must be just the _first_ arg, and so
|
||||
// we wrap it in an array so we can apply it.
|
||||
const finalMemoizeOptions = Array.isArray(memoizeOptions)
|
||||
? memoizeOptions
|
||||
: ([memoizeOptions] as MemoizeOptions)
|
||||
|
||||
const dependencies = getDependencies(funcs)
|
||||
|
||||
const memoizedResultFunc = memoize(
|
||||
function recomputationWrapper() {
|
||||
recomputations++
|
||||
// apply arguments instead of spreading for performance.
|
||||
return resultFunc!.apply(null, arguments)
|
||||
} as F,
|
||||
...finalMemoizeOptions
|
||||
)
|
||||
|
||||
// If a selector is called with the exact same arguments we don't need to traverse our dependencies again.
|
||||
const selector = memoize(function dependenciesChecker() {
|
||||
const params = []
|
||||
const length = dependencies.length
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
// apply arguments instead of spreading and mutate a local list of params for performance.
|
||||
// @ts-ignore
|
||||
params.push(dependencies[i].apply(null, arguments))
|
||||
}
|
||||
|
||||
// apply arguments instead of spreading for performance.
|
||||
lastResult = memoizedResultFunc.apply(null, params)
|
||||
return lastResult
|
||||
} as F)
|
||||
|
||||
Object.assign(selector, {
|
||||
resultFunc,
|
||||
memoizedResultFunc,
|
||||
dependencies,
|
||||
lastResult: () => lastResult,
|
||||
recomputations: () => recomputations,
|
||||
resetRecomputations: () => (recomputations = 0)
|
||||
})
|
||||
|
||||
return selector
|
||||
}
|
||||
// @ts-ignore
|
||||
return createSelector as CreateSelectorFunction<
|
||||
F,
|
||||
MemoizeFunction,
|
||||
MemoizeOptions
|
||||
>
|
||||
}
|
||||
|
||||
export interface CreateSelectorOptions<MemoizeOptions extends unknown[]> {
|
||||
memoizeOptions: MemoizeOptions[0] | MemoizeOptions
|
||||
}
|
||||
|
||||
/**
|
||||
* An instance of createSelector, customized with a given memoize implementation
|
||||
*/
|
||||
export interface CreateSelectorFunction<
|
||||
F extends (...args: unknown[]) => unknown,
|
||||
MemoizeFunction extends (func: F, ...options: any[]) => F,
|
||||
MemoizeOptions extends unknown[] = DropFirst<Parameters<MemoizeFunction>>,
|
||||
Keys = Expand<
|
||||
Pick<ReturnType<MemoizeFunction>, keyof ReturnType<MemoizeFunction>>
|
||||
>
|
||||
> {
|
||||
/** Input selectors as separate inline arguments */
|
||||
<Selectors extends SelectorArray, Result>(
|
||||
...items: [
|
||||
...Selectors,
|
||||
(...args: SelectorResultArray<Selectors>) => Result
|
||||
]
|
||||
): OutputSelector<
|
||||
Selectors,
|
||||
Result,
|
||||
(...args: SelectorResultArray<Selectors>) => Result,
|
||||
GetParamsFromSelectors<Selectors>,
|
||||
Keys
|
||||
> &
|
||||
Keys
|
||||
|
||||
/** Input selectors as separate inline arguments with memoizeOptions passed */
|
||||
<Selectors extends SelectorArray, Result>(
|
||||
...items: [
|
||||
...Selectors,
|
||||
(...args: SelectorResultArray<Selectors>) => Result,
|
||||
CreateSelectorOptions<MemoizeOptions>
|
||||
]
|
||||
): OutputSelector<
|
||||
Selectors,
|
||||
Result,
|
||||
((...args: SelectorResultArray<Selectors>) => Result),
|
||||
GetParamsFromSelectors<Selectors>,
|
||||
Keys
|
||||
> &
|
||||
Keys
|
||||
|
||||
/** Input selectors as a separate array */
|
||||
<Selectors extends SelectorArray, Result>(
|
||||
selectors: [...Selectors],
|
||||
combiner: (...args: SelectorResultArray<Selectors>) => Result,
|
||||
options?: CreateSelectorOptions<MemoizeOptions>
|
||||
): OutputSelector<
|
||||
Selectors,
|
||||
Result,
|
||||
(...args: SelectorResultArray<Selectors>) => Result,
|
||||
GetParamsFromSelectors<Selectors>,
|
||||
Keys
|
||||
> &
|
||||
Keys
|
||||
}
|
||||
|
||||
export const createSelector =
|
||||
/* #__PURE__ */ createSelectorCreator(defaultMemoize)
|
||||
|
||||
type SelectorsObject = { [key: string]: (...args: any[]) => any }
|
||||
|
||||
export interface StructuredSelectorCreator {
|
||||
<
|
||||
SelectorMap extends SelectorsObject,
|
||||
SelectorParams = MergeParameters<ObjValueTuple<SelectorMap>>
|
||||
>(
|
||||
selectorMap: SelectorMap,
|
||||
selectorCreator?: CreateSelectorFunction<any, any, any>
|
||||
): (
|
||||
// Accept an arbitrary number of parameters for all selectors
|
||||
// The annoying head/tail bit here is because TS isn't convinced that
|
||||
// the `SelectorParams` type is really an array, so we launder things.
|
||||
// Plus it matches common usage anyway.
|
||||
state: Head<SelectorParams>,
|
||||
...params: Tail<SelectorParams>
|
||||
) => {
|
||||
[Key in keyof SelectorMap]: ReturnType<SelectorMap[Key]>
|
||||
}
|
||||
|
||||
<State, Result = State>(
|
||||
selectors: { [K in keyof Result]: Selector<State, Result[K], never> },
|
||||
selectorCreator?: CreateSelectorFunction<any, any, any>
|
||||
): Selector<State, Result, never>
|
||||
}
|
||||
|
||||
// Manual definition of state and output arguments
|
||||
export const createStructuredSelector = ((
|
||||
selectors: SelectorsObject,
|
||||
selectorCreator = createSelector
|
||||
) => {
|
||||
if (typeof selectors !== 'object') {
|
||||
throw new Error(
|
||||
'createStructuredSelector expects first argument to be an object ' +
|
||||
`where each property is a selector, instead received a ${typeof selectors}`
|
||||
)
|
||||
}
|
||||
const objectKeys = Object.keys(selectors)
|
||||
const resultSelector = selectorCreator(
|
||||
// @ts-ignore
|
||||
objectKeys.map(key => selectors[key]),
|
||||
(...values: any[]) => {
|
||||
return values.reduce((composition, value, index) => {
|
||||
composition[objectKeys[index]] = value
|
||||
return composition
|
||||
}, {})
|
||||
}
|
||||
)
|
||||
return resultSelector
|
||||
}) as unknown as StructuredSelectorCreator
|
||||
3325
node_modules/reselect/src/legacyTypes/ts4.1/index.d.ts
generated
vendored
Normal file
3325
node_modules/reselect/src/legacyTypes/ts4.1/index.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
305
node_modules/reselect/src/types.ts
generated
vendored
Normal file
305
node_modules/reselect/src/types.ts
generated
vendored
Normal file
@@ -0,0 +1,305 @@
|
||||
import type { MergeParameters } from './versionedTypes'
|
||||
export type { MergeParameters } from './versionedTypes'
|
||||
|
||||
/*
|
||||
*
|
||||
* Reselect Data Types
|
||||
*
|
||||
*/
|
||||
|
||||
/** A standard selector function, which takes three generic type arguments:
|
||||
* @param State The first value, often a Redux root state object
|
||||
* @param Result The final result returned by the selector
|
||||
* @param Params All additional arguments passed into the selector
|
||||
*/
|
||||
export type Selector<
|
||||
// The state can be anything
|
||||
State = any,
|
||||
// The result will be inferred
|
||||
Result = unknown,
|
||||
// There are either 0 params, or N params
|
||||
Params extends never | readonly any[] = any[]
|
||||
// If there are 0 params, type the function as just State in, Result out.
|
||||
// Otherwise, type it as State + Params in, Result out.
|
||||
> = [Params] extends [never]
|
||||
? (state: State) => Result
|
||||
: (state: State, ...params: Params) => Result
|
||||
|
||||
/** Selectors generated by Reselect have several additional fields attached: */
|
||||
export interface OutputSelectorFields<Combiner extends UnknownFunction, Keys> {
|
||||
/** The final function passed to `createSelector` */
|
||||
resultFunc: Combiner
|
||||
/** The same function, memoized */
|
||||
memoizedResultFunc: Combiner & Keys
|
||||
/** Returns the last result calculated by the selector */
|
||||
lastResult: () => ReturnType<Combiner>
|
||||
/** An array of the input selectors */
|
||||
dependencies: SelectorArray
|
||||
/** Counts the number of times the output has been recalculated */
|
||||
recomputations: () => number
|
||||
/** Resets the count of recomputations count to 0 */
|
||||
resetRecomputations: () => number
|
||||
}
|
||||
|
||||
/** Represents the actual selectors generated by `createSelector`.
|
||||
* The selector is:
|
||||
* - "a function that takes this state + params and returns a result"
|
||||
* - plus the attached additional fields
|
||||
*/
|
||||
export type OutputSelector<
|
||||
S extends SelectorArray,
|
||||
Result,
|
||||
Combiner extends UnknownFunction,
|
||||
Params extends readonly any[] = never, // MergeParameters<S>
|
||||
Keys = {}
|
||||
> = Selector<GetStateFromSelectors<S>, Result, Params> &
|
||||
OutputSelectorFields<Combiner, Keys>
|
||||
|
||||
/** A selector that is assumed to have one additional argument, such as
|
||||
* the props from a React component
|
||||
*/
|
||||
export type ParametricSelector<State, Props, Result> = Selector<
|
||||
State,
|
||||
Result,
|
||||
[Props, ...any]
|
||||
>
|
||||
|
||||
/** A generated selector that is assumed to have one additional argument */
|
||||
export type OutputParametricSelector<
|
||||
State,
|
||||
Props,
|
||||
Result,
|
||||
Combiner extends UnknownFunction,
|
||||
Keys = {}
|
||||
> = ParametricSelector<State, Props, Result> &
|
||||
OutputSelectorFields<Combiner, Keys>
|
||||
|
||||
/** An array of input selectors */
|
||||
export type SelectorArray = ReadonlyArray<Selector>
|
||||
|
||||
/** A standard function returning true if two values are considered equal */
|
||||
export type EqualityFn = (a: any, b: any) => boolean
|
||||
|
||||
/*
|
||||
*
|
||||
* Reselect Internal Types
|
||||
*
|
||||
*/
|
||||
|
||||
/** Extracts an array of all return types from all input selectors */
|
||||
export type SelectorResultArray<Selectors extends SelectorArray> =
|
||||
ExtractReturnType<Selectors>
|
||||
|
||||
/** Determines the combined single "State" type (first arg) from all input selectors */
|
||||
export type GetStateFromSelectors<S extends SelectorArray> =
|
||||
MergeParameters<S>[0]
|
||||
|
||||
/** Determines the combined "Params" type (all remaining args) from all input selectors */
|
||||
export type GetParamsFromSelectors<
|
||||
S extends SelectorArray,
|
||||
RemainingItems extends readonly unknown[] = Tail<MergeParameters<S>>
|
||||
> = RemainingItems
|
||||
|
||||
/*
|
||||
*
|
||||
* Reselect Internal Utility Types
|
||||
*
|
||||
*/
|
||||
|
||||
/** Any function with arguments */
|
||||
export type UnknownFunction = (...args: any[]) => any
|
||||
|
||||
/** Extract the return type from all functions as a tuple */
|
||||
export type ExtractReturnType<T extends readonly UnknownFunction[]> = {
|
||||
[index in keyof T]: T[index] extends T[number] ? ReturnType<T[index]> : never
|
||||
}
|
||||
|
||||
/** First item in an array */
|
||||
export type Head<T> = T extends [any, ...any[]] ? T[0] : never
|
||||
/** All other items in an array */
|
||||
export type Tail<A> = A extends [any, ...infer Rest] ? Rest : never
|
||||
|
||||
/** Last item in an array. Recursion also enables this to work with rest syntax - where the type of rest is extracted */
|
||||
export type ReverseHead<S extends readonly unknown[][]> = Tail<S> extends [
|
||||
unknown
|
||||
]
|
||||
? S
|
||||
: Tail<S> extends readonly unknown[][]
|
||||
? ReverseHead<Tail<S>>
|
||||
: never
|
||||
|
||||
/** All elements in array except last
|
||||
*
|
||||
* Recursion makes this work also when rest syntax has been used
|
||||
* Runs _ReverseTail twice, because first pass turns last element into "never", and second pass removes it.
|
||||
**/
|
||||
export type ReverseTail<S> = _ReverseTail<_ReverseTail<S>>
|
||||
type _ReverseTail<S> = Tail<S> extends [unknown]
|
||||
? [Head<S>]
|
||||
: Tail<S> extends unknown[]
|
||||
? [Head<S>, ..._ReverseTail<Tail<S>>]
|
||||
: never
|
||||
|
||||
/** Extract only numeric keys from an array type */
|
||||
export type AllArrayKeys<A extends readonly any[]> = A extends any
|
||||
? {
|
||||
[K in keyof A]: K
|
||||
}[number]
|
||||
: never
|
||||
|
||||
export type List<A = any> = ReadonlyArray<A>
|
||||
|
||||
export type Has<U, U1> = [U1] extends [U] ? 1 : 0
|
||||
|
||||
/*
|
||||
*
|
||||
* External/Copied Utility Types
|
||||
*
|
||||
*/
|
||||
|
||||
/** The infamous "convert a union type to an intersection type" hack
|
||||
* Source: https://github.com/sindresorhus/type-fest/blob/main/source/union-to-intersection.d.ts
|
||||
* Reference: https://github.com/microsoft/TypeScript/issues/29594
|
||||
*/
|
||||
export type UnionToIntersection<Union> =
|
||||
// `extends unknown` is always going to be the case and is used to convert the
|
||||
// `Union` into a [distributive conditional
|
||||
// type](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types).
|
||||
(
|
||||
Union extends unknown
|
||||
? // The union type is used as the only argument to a function since the union
|
||||
// of function arguments is an intersection.
|
||||
(distributedUnion: Union) => void
|
||||
: // This won't happen.
|
||||
never
|
||||
) extends // Infer the `Intersection` type since TypeScript represents the positional
|
||||
// arguments of unions of functions as an intersection of the union.
|
||||
(mergedIntersection: infer Intersection) => void
|
||||
? Intersection
|
||||
: never
|
||||
|
||||
/**
|
||||
* Assorted util types for type-level conditional logic
|
||||
* Source: https://github.com/KiaraGrouwstra/typical
|
||||
*/
|
||||
export type Bool = '0' | '1'
|
||||
export type Obj<T> = { [k: string]: T }
|
||||
export type And<A extends Bool, B extends Bool> = ({
|
||||
1: { 1: '1' } & Obj<'0'>
|
||||
} & Obj<Obj<'0'>>)[A][B]
|
||||
|
||||
export type Matches<V, T> = V extends T ? '1' : '0'
|
||||
export type IsArrayType<T> = Matches<T, any[]>
|
||||
|
||||
export type Not<T extends Bool> = { '1': '0'; '0': '1' }[T]
|
||||
export type InstanceOf<V, T> = And<Matches<V, T>, Not<Matches<T, V>>>
|
||||
export type IsTuple<T extends { length: number }> = And<
|
||||
IsArrayType<T>,
|
||||
InstanceOf<T['length'], number>
|
||||
>
|
||||
|
||||
/**
|
||||
* Code to convert a union of values into a tuple.
|
||||
* Source: https://stackoverflow.com/a/55128956/62937
|
||||
*/
|
||||
type Push<T extends any[], V> = [...T, V]
|
||||
|
||||
type LastOf<T> = UnionToIntersection<
|
||||
T extends any ? () => T : never
|
||||
> extends () => infer R
|
||||
? R
|
||||
: never
|
||||
|
||||
// TS4.1+
|
||||
export type TuplifyUnion<
|
||||
T,
|
||||
L = LastOf<T>,
|
||||
N = [T] extends [never] ? true : false
|
||||
> = true extends N ? [] : Push<TuplifyUnion<Exclude<T, L>>, L>
|
||||
|
||||
/**
|
||||
* Converts "the values of an object" into a tuple, like a type-level `Object.values()`
|
||||
* Source: https://stackoverflow.com/a/68695508/62937
|
||||
*/
|
||||
export type ObjValueTuple<
|
||||
T,
|
||||
KS extends any[] = TuplifyUnion<keyof T>,
|
||||
R extends any[] = []
|
||||
> = KS extends [infer K, ...infer KT]
|
||||
? ObjValueTuple<T, KT, [...R, T[K & keyof T]]>
|
||||
: R
|
||||
|
||||
/** Utility type to infer the type of "all params of a function except the first", so we can determine what arguments a memoize function accepts */
|
||||
export type DropFirst<T extends unknown[]> = T extends [unknown, ...infer U]
|
||||
? U
|
||||
: never
|
||||
|
||||
/**
|
||||
* Expand an item a single level, or recursively.
|
||||
* Source: https://stackoverflow.com/a/69288824/62937
|
||||
*/
|
||||
export type Expand<T> = T extends (...args: infer A) => infer R
|
||||
? (...args: Expand<A>) => Expand<R>
|
||||
: T extends infer O
|
||||
? { [K in keyof O]: O[K] }
|
||||
: never
|
||||
|
||||
export type ExpandRecursively<T> = T extends (...args: infer A) => infer R
|
||||
? (...args: ExpandRecursively<A>) => ExpandRecursively<R>
|
||||
: T extends object
|
||||
? T extends infer O
|
||||
? { [K in keyof O]: ExpandRecursively<O[K]> }
|
||||
: never
|
||||
: T
|
||||
|
||||
type Identity<T> = T
|
||||
/**
|
||||
* Another form of type value expansion
|
||||
* Source: https://github.com/microsoft/TypeScript/issues/35247
|
||||
*/
|
||||
export type Mapped<T> = Identity<{ [k in keyof T]: T[k] }>
|
||||
|
||||
/**
|
||||
* Fully expand a type, deeply
|
||||
* Source: https://github.com/millsp/ts-toolbelt (`Any.Compute`)
|
||||
*/
|
||||
|
||||
type ComputeDeep<A, Seen = never> = A extends BuiltIn
|
||||
? A
|
||||
: If2<
|
||||
Has<Seen, A>,
|
||||
A,
|
||||
A extends Array<any>
|
||||
? A extends Array<Record<Key, any>>
|
||||
? Array<
|
||||
{
|
||||
[K in keyof A[number]]: ComputeDeep<A[number][K], A | Seen>
|
||||
} & unknown
|
||||
>
|
||||
: A
|
||||
: A extends ReadonlyArray<any>
|
||||
? A extends ReadonlyArray<Record<Key, any>>
|
||||
? ReadonlyArray<
|
||||
{
|
||||
[K in keyof A[number]]: ComputeDeep<A[number][K], A | Seen>
|
||||
} & unknown
|
||||
>
|
||||
: A
|
||||
: { [K in keyof A]: ComputeDeep<A[K], A | Seen> } & unknown
|
||||
>
|
||||
|
||||
export type If2<B extends Boolean2, Then, Else = never> = B extends 1
|
||||
? Then
|
||||
: Else
|
||||
|
||||
export type Boolean2 = 0 | 1
|
||||
|
||||
export type Key = string | number | symbol
|
||||
|
||||
export type BuiltIn =
|
||||
| Function
|
||||
| Error
|
||||
| Date
|
||||
| { readonly [Symbol.toStringTag]: string }
|
||||
| RegExp
|
||||
| Generator
|
||||
1
node_modules/reselect/src/versionedTypes/index.ts
generated
vendored
Normal file
1
node_modules/reselect/src/versionedTypes/index.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export { MergeParameters } from './ts47-mergeParameters'
|
||||
14
node_modules/reselect/src/versionedTypes/package.dist.json
generated
vendored
Normal file
14
node_modules/reselect/src/versionedTypes/package.dist.json
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"typesVersions": {
|
||||
">=4.7": {
|
||||
"index": [
|
||||
"./ts47-mergeParameters.d.ts"
|
||||
]
|
||||
},
|
||||
"<4.7": {
|
||||
"index": [
|
||||
"./ts46-mergeParameters.d.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
171
node_modules/reselect/src/versionedTypes/ts46-mergeParameters.ts
generated
vendored
Normal file
171
node_modules/reselect/src/versionedTypes/ts46-mergeParameters.ts
generated
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
import type {
|
||||
UnknownFunction,
|
||||
Expand,
|
||||
TuplifyUnion,
|
||||
Has,
|
||||
List,
|
||||
IsTuple
|
||||
} from '../types'
|
||||
|
||||
/** Given a set of input selectors, extracts the intersected parameters to determine
|
||||
* what values can actually be passed to all of the input selectors at once
|
||||
* WARNING: "you are not expected to understand this" :)
|
||||
*/
|
||||
export type MergeParameters<
|
||||
// The actual array of input selectors
|
||||
T extends readonly UnknownFunction[],
|
||||
// Given those selectors, we do several transformations on the types in sequence:
|
||||
// 1) Extract "the type of parameters" for each input selector, so that we now have
|
||||
// a tuple of all those parameters
|
||||
ParamsArrays extends readonly any[][] = ExtractParams<T>,
|
||||
// 2) Transpose the parameter tuples.
|
||||
// Originally, we have nested arrays with "all params from input", "from input 2", etc:
|
||||
// `[ [i1a, i1b, i1c], [i2a, i2b, i2c], [i3a, i3b, i3c] ],
|
||||
// In order to intersect the params at each index, we need to transpose them so that
|
||||
// we have "all the first args", "all the second args", and so on:
|
||||
// `[ [i1a, i2a, i3a], [i1b, i2b, i3b], [i1c, i2c, i3c] ]
|
||||
// Unfortunately, this step also turns the arrays into a union, and weirder, it is
|
||||
// a union of all possible combinations for all input functions, so there's duplicates.
|
||||
TransposedArrays = Transpose<ParamsArrays>,
|
||||
// 3) Turn the union of arrays back into a nested tuple. Order does not matter here.
|
||||
TuplifiedArrays extends any[] = TuplifyUnion<TransposedArrays>,
|
||||
// 4) Find the longest params array out of the ones we have.
|
||||
// Note that this is actually the _nested_ data we wanted out of the transpose step,
|
||||
// so it has all the right pieces we need.
|
||||
LongestParamsArray extends readonly any[] = LongestArray<TuplifiedArrays>
|
||||
> =
|
||||
// After all that preparation work, we can actually do parameter extraction.
|
||||
// These steps work somewhat inside out (jump ahead to the middle):
|
||||
// 11) Finally, after all that, run a shallow expansion on the values to make the user-visible
|
||||
// field details more readable when viewing the selector's type in a hover box.
|
||||
ExpandItems<
|
||||
// 10) Tuples can have field names attached, and it seems to work better to remove those
|
||||
RemoveNames<{
|
||||
// 5) We know the longest params array has N args. Loop over the indices of that array.
|
||||
// 6) For each index, do a check to ensure that we're _only_ checking numeric indices,
|
||||
// not any field names for array functions like `slice()`
|
||||
[index in keyof LongestParamsArray]: LongestParamsArray[index] extends LongestParamsArray[number]
|
||||
? // 9) Any object types that were intersected may have had
|
||||
IgnoreInvalidIntersections<
|
||||
// 8) Then, intersect all of the parameters for this arg together.
|
||||
IntersectAll<
|
||||
// 7) Since this is a _nested_ array, extract the right sub-array for this index
|
||||
LongestParamsArray[index]
|
||||
>
|
||||
>
|
||||
: never
|
||||
}>
|
||||
>
|
||||
|
||||
/*
|
||||
*
|
||||
* Reselect Internal Utility Types
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* Reselect Internal Utility Types
|
||||
*
|
||||
*/
|
||||
|
||||
/** An object with no fields */
|
||||
type EmptyObject = {
|
||||
[K in any]: never
|
||||
}
|
||||
|
||||
type IgnoreInvalidIntersections<T> = T extends EmptyObject ? never : T
|
||||
|
||||
/** Extract the parameters from all functions as a tuple */
|
||||
export type ExtractParams<T extends readonly UnknownFunction[]> = {
|
||||
[index in keyof T]: T[index] extends T[number] ? Parameters<T[index]> : never
|
||||
}
|
||||
|
||||
/** Recursively expand all fields in an object for easier reading */
|
||||
export type ExpandItems<T extends readonly unknown[]> = {
|
||||
[index in keyof T]: T[index] extends T[number] ? Expand<T[index]> : never
|
||||
}
|
||||
|
||||
/** Select the longer of two arrays */
|
||||
export type Longest<L extends List, L1 extends List> = L extends unknown
|
||||
? L1 extends unknown
|
||||
? { 0: L1; 1: L }[Has<keyof L, keyof L1>]
|
||||
: never
|
||||
: never
|
||||
|
||||
/** Recurse over a nested array to locate the longest one.
|
||||
* Acts like a type-level `reduce()`
|
||||
*/
|
||||
export type LongestArray<S extends readonly any[][]> =
|
||||
// If this isn't a tuple, all indices are the same, we can't tell a difference
|
||||
IsTuple<S> extends '0'
|
||||
? // so just return the type of the first item
|
||||
S[0]
|
||||
: // If there's two nested arrays remaining, compare them
|
||||
S extends [any[], any[]]
|
||||
? Longest<S[0], S[1]>
|
||||
: // If there's more than two, extract their types, treat the remainder as a smaller array
|
||||
S extends [any[], any[], ...infer Rest]
|
||||
? // then compare those two, recurse through the smaller array, and compare vs its result
|
||||
Longest<
|
||||
Longest<S[0], S[1]>,
|
||||
Rest extends any[][] ? LongestArray<Rest> : []
|
||||
>
|
||||
: // If there's one item left, return it
|
||||
S extends [any[]]
|
||||
? S[0]
|
||||
: never
|
||||
|
||||
/** Recursive type for intersecting together all items in a tuple, to determine
|
||||
* the final parameter type at a given argument index in the generated selector. */
|
||||
export type IntersectAll<T extends any[]> = IsTuple<T> extends '0'
|
||||
? T[0]
|
||||
: _IntersectAll<T>
|
||||
|
||||
type IfJustNullish<T, True, False> = [T] extends [undefined | null]
|
||||
? True
|
||||
: False
|
||||
|
||||
/** Intersect a pair of types together, for use in parameter type calculation.
|
||||
* This is made much more complex because we need to correctly handle cases
|
||||
* where a function has fewer parameters and the type is `undefined`, as well as
|
||||
* optional params or params that have `null` or `undefined` as part of a union.
|
||||
*
|
||||
* If the next type by itself is `null` or `undefined`, we exclude it and return
|
||||
* the other type. Otherwise, intersect them together.
|
||||
*/
|
||||
type _IntersectAll<T, R = unknown> = T extends [infer First, ...infer Rest]
|
||||
? _IntersectAll<Rest, IfJustNullish<First, R, R & First>>
|
||||
: R
|
||||
|
||||
/*
|
||||
*
|
||||
* External/Copied Utility Types
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Removes field names from a tuple
|
||||
* Source: https://stackoverflow.com/a/63571175/62937
|
||||
*/
|
||||
type RemoveNames<T extends readonly any[]> = [any, ...T] extends [
|
||||
any,
|
||||
...infer U
|
||||
]
|
||||
? U
|
||||
: never
|
||||
|
||||
/**
|
||||
* Transposes nested arrays
|
||||
* Source: https://stackoverflow.com/a/66303933/62937
|
||||
*/
|
||||
type Transpose<T> = T[Extract<
|
||||
keyof T,
|
||||
T extends readonly any[] ? number : unknown
|
||||
>] extends infer V
|
||||
? {
|
||||
[K in keyof V]: {
|
||||
[L in keyof T]: K extends keyof T[L] ? T[L][K] : undefined
|
||||
}
|
||||
}
|
||||
: never
|
||||
66
node_modules/reselect/src/versionedTypes/ts47-mergeParameters.ts
generated
vendored
Normal file
66
node_modules/reselect/src/versionedTypes/ts47-mergeParameters.ts
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
// This entire implementation courtesy of Anders Hjelsberg:
|
||||
// https://github.com/microsoft/TypeScript/pull/50831#issuecomment-1253830522
|
||||
|
||||
import { ReverseHead, ReverseTail } from '../types'
|
||||
|
||||
type UnknownFunction = (...args: any[]) => any
|
||||
|
||||
type LongestTuple<T> = T extends [infer U extends unknown[]]
|
||||
? U
|
||||
: T extends [infer U, ...infer R extends unknown[][]]
|
||||
? MostProperties<U, LongestTuple<R>>
|
||||
: never
|
||||
|
||||
type MostProperties<T, U> = keyof U extends keyof T ? T : U
|
||||
|
||||
type ElementAt<T, N extends keyof any> = N extends keyof T ? T[N] : unknown
|
||||
|
||||
type ElementsAt<T, N extends keyof any> = {
|
||||
[K in keyof T]: ElementAt<T[K], N>
|
||||
}
|
||||
|
||||
type Intersect<T extends readonly unknown[]> = T extends []
|
||||
? unknown
|
||||
: T extends [infer H, ...infer T]
|
||||
? H & Intersect<T>
|
||||
: T[number]
|
||||
|
||||
type MergeTuples<T, L extends unknown[] = LongestTuple<T>> = {
|
||||
[K in keyof L]: Intersect<
|
||||
ElementsAt<T, K> extends readonly unknown[] ? ElementsAt<T, K> : never
|
||||
>
|
||||
}
|
||||
|
||||
type ExtractParameters<T extends readonly UnknownFunction[]> = {
|
||||
[K in keyof T]: Parameters<T[K]>
|
||||
}
|
||||
|
||||
export type MergeParameters<T extends readonly UnknownFunction[]> =
|
||||
'0' extends keyof T
|
||||
? MergeTuples<MakeRestExplicit<ExtractParameters<T>>>
|
||||
: Parameters<T[number]>
|
||||
|
||||
type HasRest<S extends readonly unknown[]> = number extends S['length']
|
||||
? true
|
||||
: false
|
||||
|
||||
type HasExplicit<S extends readonly unknown[]> = '0' extends keyof S
|
||||
? true
|
||||
: false
|
||||
|
||||
type HasCombined<S extends readonly unknown[]> = true extends HasExplicit<S> &
|
||||
HasRest<S>
|
||||
? true
|
||||
: false
|
||||
|
||||
type MakeRestExplicit<T extends readonly unknown[][]> =
|
||||
true extends HasCombined<T>
|
||||
? [
|
||||
...ReverseTail<T>,
|
||||
ReverseHead<T> extends readonly unknown[]
|
||||
? ReverseHead<T>[number]
|
||||
: never
|
||||
]
|
||||
: true extends HasRest<T>
|
||||
? [...T]
|
||||
: T
|
||||
Reference in New Issue
Block a user