reselect
Version:
Selectors for Redux.
118 lines (108 loc) • 2.99 kB
text/typescript
// This entire implementation courtesy of Anders Hjelsberg:
// https://github.com/microsoft/TypeScript/pull/50831#issuecomment-1253830522
import type { AnyFunction } from '../types'
/**
* Represents the longest array within an array of arrays.
*
* @template ArrayOfTuples An array of arrays.
*
* @internal
*/
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 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<
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 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<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<
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<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<FunctionsArray extends readonly AnyFunction[]> =
'0' extends keyof FunctionsArray
? MergeTuples<ExtractParameters<FunctionsArray>>
: Parameters<FunctionsArray[number]>