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, TransposedArrays = Transpose, TuplifiedArrays extends any[] = TuplifyUnion, LongestParamsArray extends readonly any[] = LongestArray> = ExpandItems> : never; }>>; /** An object with no fields */ type EmptyObject = { [K in any]: never; }; type IgnoreInvalidIntersections = T extends EmptyObject ? never : T; /** Extract the parameters from all functions as a tuple */ export type ExtractParams = { [index in keyof T]: T[index] extends T[number] ? Parameters : never; }; /** Recursively expand all fields in an object for easier reading */ export type ExpandItems = { [index in keyof T]: T[index] extends T[number] ? Expand : never; }; /** Select the longer of two arrays */ export type Longest = L extends unknown ? L1 extends unknown ? { 0: L1; 1: L; }[Has] : never : never; /** Recurse over a nested array to locate the longest one. * Acts like a type-level `reduce()` */ export type LongestArray = IsTuple extends '0' ? S[0] : S extends [any[], any[]] ? Longest : S extends [any[], any[], ...infer Rest] ? Longest, Rest extends any[][] ? LongestArray : []> : 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 = IsTuple extends '0' ? T[0] : _IntersectAll; type IfJustNullish = [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 extends [infer First, ...infer Rest] ? _IntersectAll> : R; /** * Removes field names from a tuple * Source: https://stackoverflow.com/a/63571175/62937 */ type RemoveNames = [any, ...T] extends [ any, ...infer U ] ? U : never; /** * Transposes nested arrays * Source: https://stackoverflow.com/a/66303933/62937 */ type Transpose = T[Extract] extends infer V ? { [K in keyof V]: { [L in keyof T]: K extends keyof T[L] ? T[L][K] : undefined; }; } : never; export {};