import { isType } from '../internals'; import { isAny } from '../any/infrastructure'; import { equals } from '../comparison/infrastructure'; import { isNever } from '../never/infrastructure'; export * from './domain'; /** * Evaluates if the specified type is an array. * * @example * type A = IsArray; * // ^? true * type B = IsArray; * // ^? false * type C = IsArray; * // ^? false */ export type isArray = isType; /** * A utility type that checks whether a given array is empty. * Returns 'true' if the array is empty, and 'false' otherwise. * * @example * type Result1 = IsEmptyArray<[]>; * // ^? true * type Result2 = IsEmptyArray<[1, 2, 3]>; * // ^? false */ export type isEmptyArray = T extends [] ? true : false; /** * Evaluates if the specified type is a tuple. * * @example * type A = IsTuple<[number, string]>; * // ^? true * type B = IsTuple; * // ^? false * type C = IsTuple; * // ^? false */ export type isTuple = $if | isAny, { then: false; else: T extends [infer _A, ...(infer _B)] ? true : false; }>; /** * Checks if a tuple `T` includes a specific type `TypeToSearch`. * @example * type Result = tupleIncludes<[number, string, boolean], string>; * // ^? true * type Result2 = tupleIncludes<[number, string, boolean], object>; * // ^? false */ export type tupleIncludes = T extends [infer Current, ...infer Rest] ? equals extends true ? true : tupleIncludes : false; /** * Generates a tuple type with the specified length and type. * * If you do not pass a Length will return a nLenghtTuple * (it works like an Array on variables declaration but differs on extends generics) * * @example * type A = Tuple; * // ^? [number, number, number] * type B = Tuple; * // ^? [] | [number, ...number[]] */ export type Tuple = isNever extends true ? nLengthTuple : _Tuple; type _Tuple = result['length'] extends Length ? result : [..._Tuple]; /** * `Shift` takes a tuple and returns a new tuple excluding the first element from the original tuple. * * @example * type A = Shift<[1, 2, 3]>; * // ^? [2, 3] */ export type Shift = T extends [infer _, ...infer Result] ? Result : []; /** * `Pop` takes a tuple and returns a new tuple excluding the last element from the original tuple. * * @example * type A = Pop<[1, 2, 3]>; * // ^? [1, 2] */ export type Pop = T extends [...infer Result, infer _] ? Result : []; /** * `ShiftRecursive` recursively generates all possible subsets of a tuple by successively excluding * the first element in each iteration until the length of the tuple is equal to a specified minimum length. * * @example * type A = ShiftRecursive<[1, 2, 3]>; * // ^? [], [2, 3], [3] */ export type ShiftRecursive> = T['length'] extends minLength ? Result : ShiftRecursive; /** * `PopRecursive` recursively generates all possible subsets of a tuple by successively excluding * the last element in each iteration until the length of the tuple is zero. * * @example * type A = PopRecursive<[1, 2, 3]>; * // ^? [1, 2] | [1] | [] */ export type PopRecursive> = T['length'] extends 0 ? Result : PopRecursive; /** * `UnionToTupleCombination` converts a union into a combinations of tuples. * * @example * type A = UnionToTupleCombination<'a' | 'b' | 'c'>; * // ^? ['a', 'b'] | ['b', 'a'] */ export type UnionToTupleCombination = isNever extends true ? _Result : T extends infer ActualKey ? UnionToTupleCombination, [..._Result, ActualKey]> : never; /** * Extracts the indexes of a tuple type `T` and returns them as a union type. * It excludes the extra keys present on Array objects, isolating only the actual * tuple indexes. * * @example * type Indices = getIndexes<[string, number, boolean]>; * // ^? "0" | "1" | "2" * type Empty = getIndexes<[]>; * // ^? never */ export type getIndexes = Exclude;