reselect
Version:
Selectors for Redux.
67 lines (52 loc) • 1.88 kB
text/typescript
// 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