// ============================================================================ // Helpers // ============================================================================ type InternalTupleBuildArray< N extends number, Acc extends readonly unknown[] = [], > = Acc["length"] extends N ? Acc : InternalTupleBuildArray /** * @description Build a tuple of length N with unknown elements. * * @example * ``` * // Expect: [unknown, unknown] * type Example1 = TupleLengthN<2> * // Expect: [] * type Example2 = TupleLengthN<0> * ``` */ export type TupleLengthN = InternalTupleBuildArray // ============================================================================ // Primitives // ============================================================================ /** * @description Get an empty tuple type. * * @example * ``` * // Expect: [] * type Example1 = TupleEmpty * // Expect: true * type Example2 = TupleIsEmpty * ``` */ export type TupleEmpty = [] /** * @description Build a single-element tuple. * * @example * ``` * // Expect: [number] * type Example1 = TupleSingleton * // Expect: [string] * type Example2 = TupleSingleton<'a'> * ``` */ export type TupleSingleton = [T] /** * @description Build a two-element tuple. * * @example * ``` * // Expect: [number, string] * type Example1 = TuplePair * // Expect: [boolean, boolean] * type Example2 = TuplePair * ``` */ export type TuplePair = [T, U] /** * @description Build a three-element tuple. * * @example * ``` * // Expect: [number, string, boolean] * type Example1 = TupleTriple * // Expect: [1, 2, 3] * type Example2 = TupleTriple<1, 2, 3> * ``` */ export type TupleTriple = [T, U, V] /** * @description Build a four-element tuple. * * @example * ``` * // Expect: [number, string, boolean, null] * type Example1 = TupleQuad * // Expect: [1, 2, 3, 4] * type Example2 = TupleQuad<1, 2, 3, 4> * ``` */ export type TupleQuad = [T, U, V, W] /** * @description Build a five-element tuple. * * @example * ``` * // Expect: [1, 2, 3, 4, 5] * type Example1 = TupleQuint<1, 2, 3, 4, 5> * // Expect: [string, string, string, string, string] * type Example2 = TupleQuint * ``` */ export type TupleQuint = [T, U, V, W, X] /** * @description Build a tuple of length 2. * * @example * ``` * // Expect: [unknown, unknown] * type Example1 = TupleLength2 * // Expect: 2 * type Example2 = TupleLength * ``` */ export type TupleLength2 = [unknown, unknown] /** * @description Build a tuple of length 3. * * @example * ``` * // Expect: [unknown, unknown, unknown] * type Example1 = TupleLength3 * // Expect: 3 * type Example2 = TupleLength * ``` */ export type TupleLength3 = [unknown, unknown, unknown] /** * @description Build a tuple of length 4. * * @example * ``` * // Expect: [unknown, unknown, unknown, unknown] * type Example1 = TupleLength4 * // Expect: 4 * type Example2 = TupleLength * ``` */ export type TupleLength4 = [unknown, unknown, unknown, unknown] /** * @description Build a tuple of length 5. * * @example * ``` * // Expect: [unknown, unknown, unknown, unknown, unknown] * type Example1 = TupleLength5 * // Expect: 5 * type Example2 = TupleLength * ``` */ export type TupleLength5 = [unknown, unknown, unknown, unknown, unknown] /** * @description Build a tuple of length 6. * * @example * ``` * // Expect: [unknown, unknown, unknown, unknown, unknown, unknown] * type Example1 = TupleLength6 * // Expect: 6 * type Example2 = TupleLength * ``` */ export type TupleLength6 = [unknown, unknown, unknown, unknown, unknown, unknown] /** * @description Build a tuple of length 7. * * @example * ``` * // Expect: [unknown, unknown, unknown, unknown, unknown, unknown, unknown] * type Example1 = TupleLength7 * // Expect: 7 * type Example2 = TupleLength * ``` */ export type TupleLength7 = [unknown, unknown, unknown, unknown, unknown, unknown, unknown] // ============================================================================ // Validation // ============================================================================ /** * @description Check if a type is a tuple (not a generic array). * * @example * ``` * // Expect: true * type Example1 = TupleIsTuple<[number, string]> * // Expect: false * type Example2 = TupleIsTuple * ``` */ export type TupleIsTuple = number extends T["length"] ? false : true /** * @description Check if a tuple is empty. * * @example * ``` * // Expect: true * type Example1 = TupleIsEmpty<[]> * // Expect: false * type Example2 = TupleIsEmpty<[number]> * ``` */ export type TupleIsEmpty = T extends [] ? true : false /** * @description Check if a tuple is non-empty. * * @example * ``` * // Expect: true * type Example1 = TupleIsNonEmpty<[number]> * // Expect: false * type Example2 = TupleIsNonEmpty<[]> * ``` */ export type TupleIsNonEmpty = T extends [] ? false : true /** * @description Check if a tuple is readonly. * * @example * ``` * // Expect: true * type Example1 = TupleIsReadonly * // Expect: false * type Example2 = TupleIsReadonly<[number]> * ``` */ export type TupleIsReadonly = T extends unknown[] ? false : true /** * @description Check if a tuple has fixed length. * * @example * ``` * // Expect: true * type Example1 = TupleIsFixedLength<[number, string]> * // Expect: false * type Example2 = TupleIsFixedLength * ``` */ export type TupleIsFixedLength = TupleIsTuple /** * @description Check if a tuple type is never. * * @example * ``` * // Expect: true * type Example1 = TupleIsNever * // Expect: false * type Example2 = TupleIsNever<[]> * ``` */ export type TupleIsNever = [T] extends [never] ? true : false type InternalIsAny = 0 extends 1 & T ? true : false /** * @description Check if a tuple type is any. * * @example * ``` * // Expect: true * type Example1 = TupleIsAny * // Expect: false * type Example2 = TupleIsAny<[]> * ``` */ export type TupleIsAny = InternalIsAny type InternalIsUnknown = InternalIsAny extends true ? false : unknown extends T ? T extends unknown ? true : false : false /** * @description Check if a tuple type is unknown. * * @example * ``` * // Expect: true * type Example1 = TupleIsUnknown * // Expect: false * type Example2 = TupleIsUnknown<[]> * ``` */ export type TupleIsUnknown = InternalIsUnknown type InternalIsUnion = T extends unknown ? ([U] extends [T] ? false : true) : false /** * @description Check if a tuple type is a union. * * @example * ``` * // Expect: true * type Example1 = TupleIsUnion<[number] | [string]> * // Expect: false * type Example2 = TupleIsUnion<[number]> * ``` */ export type TupleIsUnion = InternalIsUnion /** * @description Check if a type is array-like. * * @example * ``` * // Expect: true * type Example1 = TupleIsArrayLike<[number]> * // Expect: false * type Example2 = TupleIsArrayLike * ``` */ export type TupleIsArrayLike = T extends readonly unknown[] ? true : false /** * @description Check if a tuple contains a never element. * * @example * ``` * // Expect: true * type Example1 = TupleHasNeverElement<[never, number]> * // Expect: false * type Example2 = TupleHasNeverElement<[number, string]> * ``` */ export type TupleHasNeverElement = T extends readonly [ infer First, ...infer Rest, ] ? [First] extends [never] ? true : TupleHasNeverElement : false /** * @description Check if all tuple elements are optional (include undefined). * * @example * ``` * // Expect: true * type Example1 = TupleIsAllUndefinedable<[number | undefined, string | undefined]> * // Expect: false * type Example2 = TupleIsAllUndefinedable<[number, string | undefined]> * ``` */ export type TupleIsAllUndefinedable = T extends readonly [ infer First, ...infer Rest, ] ? undefined extends First ? TupleIsAllUndefinedable : false : true /** * @description Check if all tuple elements are required (exclude undefined). * * @example * ``` * // Expect: true * type Example1 = TupleIsAllNonUndefinedable<[number, string]> * // Expect: false * type Example2 = TupleIsAllNonUndefinedable<[number | undefined, string]> * ``` */ export type TupleIsAllNonUndefinedable = T extends readonly [ infer First, ...infer Rest, ] ? undefined extends First ? false : TupleIsAllNonUndefinedable : true /** * @description Check if all tuple elements are the same type. * * @example * ``` * // Expect: true * type Example1 = TupleIsHomogeneous<[number, number, number]> * // Expect: false * type Example2 = TupleIsHomogeneous<[number, string]> * ``` */ export type TupleIsHomogeneous = T extends readonly [ infer First, ...infer Rest, ] ? TupleIsEqual> : true /** * @description Check if all tuple elements are distinct. * * @example * ``` * // Expect: true * type Example1 = TupleIsDistinct<[1, 2, 3]> * // Expect: false * type Example2 = TupleIsDistinct<[1, 2, 1]> * ``` */ export type TupleIsDistinct = T extends readonly [ infer First, ...infer Rest, ] ? TupleIncludes extends true ? false : TupleIsDistinct : true // ============================================================================ // Comparison // ============================================================================ type InternalIsEqual = (() => T extends A ? 1 : 2) extends () => T extends B ? 1 : 2 ? true : false /** * @description Check if two tuples are element-wise equal. * * @example * ``` * // Expect: true * type Example1 = TupleIsEqual<[1, 2], [1, 2]> * // Expect: false * type Example2 = TupleIsEqual<[1, 2], [2, 1]> * ``` */ export type TupleIsEqual< A extends readonly unknown[], B extends readonly unknown[], > = A extends readonly [infer FirstA, ...infer RestA] ? B extends readonly [infer FirstB, ...infer RestB] ? InternalIsEqual extends true ? TupleIsEqual : false : false : B extends [] ? true : false /** * @description Check if a tuple starts with a prefix tuple. * * @example * ``` * // Expect: true * type Example1 = TupleStartsWith<[1, 2, 3], [1, 2]> * // Expect: false * type Example2 = TupleStartsWith<[1, 2, 3], [2, 3]> * ``` */ export type TupleStartsWith< T extends readonly unknown[], P extends readonly unknown[], > = P extends [] ? true : T extends readonly [infer FirstT, ...infer RestT] ? P extends readonly [infer FirstP, ...infer RestP] ? InternalIsEqual extends true ? TupleStartsWith : false : false : false /** * @description Check if a tuple ends with a suffix tuple. * * @example * ``` * // Expect: true * type Example1 = TupleEndsWith<[1, 2, 3], [2, 3]> * // Expect: false * type Example2 = TupleEndsWith<[1, 2, 3], [1, 3]> * ``` */ export type TupleEndsWith< T extends readonly unknown[], S extends readonly unknown[], > = TupleStartsWith, TupleReverse> /** * @description Check if a tuple includes a value. * * @example * ``` * // Expect: true * type Example1 = TupleIncludes<[1, 2, 3], 2> * // Expect: false * type Example2 = TupleIncludes<[1, 2, 3], 4> * ``` */ export type TupleIncludes = T extends readonly [ infer First, ...infer Rest, ] ? InternalIsEqual extends true ? true : TupleIncludes : false type InternalTupleCompareHelper = InternalTupleBuildArray extends InternalTupleBuildArray ? 0 : InternalTupleBuildArray extends [...InternalTupleBuildArray, ...infer _] ? 1 : -1 /** * @description Check if two tuples have the same length. * * @example * ``` * // Expect: true * type Example1 = TupleSameLength<[1, 2], ['a', 'b']> * // Expect: false * type Example2 = TupleSameLength<[1], ['a', 'b']> * ``` */ export type TupleSameLength = InternalTupleCompareHelper extends 0 ? true : false /** * @description Alias of TupleStartsWith. * * @example * ``` * // Expect: true * type Example1 = TupleIsPrefix<[1, 2, 3], [1, 2]> * // Expect: false * type Example2 = TupleIsPrefix<[1, 2, 3], [2, 3]> * ``` */ export type TupleIsPrefix< T extends readonly unknown[], P extends readonly unknown[], > = TupleStartsWith /** * @description Alias of TupleEndsWith. * * @example * ``` * // Expect: true * type Example1 = TupleIsSuffix<[1, 2, 3], [2, 3]> * // Expect: false * type Example2 = TupleIsSuffix<[1, 2, 3], [1, 3]> * ``` */ export type TupleIsSuffix< T extends readonly unknown[], S extends readonly unknown[], > = TupleEndsWith /** * @description Check if every element in A is included in B. * * @example * ``` * // Expect: true * type Example1 = TupleIsSubset<[1, 2], [1, 2, 3]> * // Expect: false * type Example2 = TupleIsSubset<[1, 4], [1, 2, 3]> * ``` */ export type TupleIsSubset< A extends readonly unknown[], B extends readonly unknown[], > = A extends readonly [infer First, ...infer Rest] ? TupleIncludes extends true ? TupleIsSubset : false : true /** * @description Check if every element in B is included in A. * * @example * ``` * // Expect: true * type Example1 = TupleIsSuperset<[1, 2, 3], [1, 2]> * // Expect: false * type Example2 = TupleIsSuperset<[1, 2], [1, 3]> * ``` */ export type TupleIsSuperset< A extends readonly unknown[], B extends readonly unknown[], > = TupleIsSubset /** * @description Compare tuple lengths and return -1, 0, or 1. * * @example * ``` * // Expect: 0 * type Example1 = TupleCompareLength<[1, 2], ['a', 'b']> * // Expect: -1 * type Example2 = TupleCompareLength<[1], ['a', 'b']> * ``` */ export type TupleCompareLength< A extends readonly unknown[], B extends readonly unknown[], > = InternalTupleCompareHelper /** * @description Check if two tuple types are strictly equal. * * @example * ``` * // Expect: true * type Example1 = TupleIsStrictEqual<[1, 2], [1, 2]> * // Expect: false * type Example2 = TupleIsStrictEqual<[1, 2], [2, 1]> * ``` */ export type TupleIsStrictEqual = InternalIsEqual /** * @description Deeply compare two tuples, recursing into nested tuples. * * @example * ``` * // Expect: true * type Example1 = TupleIsEqualDeep<[[1], [2]], [[1], [2]]> * // Expect: false * type Example2 = TupleIsEqualDeep<[[1], [2]], [[2], [1]]> * ``` */ export type TupleIsEqualDeep< A extends readonly unknown[], B extends readonly unknown[], > = A extends readonly [infer FirstA, ...infer RestA] ? B extends readonly [infer FirstB, ...infer RestB] ? FirstA extends readonly unknown[] ? FirstB extends readonly unknown[] ? TupleIsEqualDeep extends true ? TupleIsEqualDeep : false : false : InternalIsEqual extends true ? TupleIsEqualDeep : false : false : B extends [] ? true : false /** * @description Compare tuples lexicographically, returning -1, 0, or 1. * * @example * ``` * // Expect: 0 * type Example1 = TupleCompareLexicographic<[1, 2], [1, 2]> * // Expect: -1 | 1 * type Example2 = TupleCompareLexicographic<[1, 2], [1, 3]> * ``` */ export type TupleCompareLexicographic< A extends readonly unknown[], B extends readonly unknown[], > = A extends readonly [infer FirstA, ...infer RestA] ? B extends readonly [infer FirstB, ...infer RestB] ? InternalIsEqual extends true ? TupleCompareLexicographic : -1 | 1 : 1 : B extends [] ? 0 : -1 /** * @description Check if two tuples are equal ignoring element order. * * @example * ``` * // Expect: true * type Example1 = TupleEqualsIgnoringOrder<[1, 2], [2, 1]> * // Expect: false * type Example2 = TupleEqualsIgnoringOrder<[1, 2], [1, 2, 3]> * ``` */ export type TupleEqualsIgnoringOrder = TupleSameLength extends true ? TupleIsSubset, TupleUnique> extends true ? TupleIsSubset, TupleUnique> : false : false /** * @description Alias of TupleIsSuperset. * * @example * ``` * // Expect: true * type Example1 = TupleContainsAll<[1, 2, 3], [1, 2]> * // Expect: false * type Example2 = TupleContainsAll<[1, 2], [1, 3]> * ``` */ export type TupleContainsAll< A extends readonly unknown[], B extends readonly unknown[], > = TupleIsSuperset // ============================================================================ // Query // ============================================================================ type InternalTupleIndexCounter< T extends readonly unknown[], U, Count extends readonly unknown[] = [], > = T extends readonly [infer First, ...infer Rest] ? InternalIsEqual extends true ? Count["length"] : InternalTupleIndexCounter : -1 /** * @description Get the length of a tuple. * * @example * ``` * // Expect: 3 * type Example1 = TupleLength<[1, 2, 3]> * // Expect: 0 * type Example2 = TupleLength<[]> * ``` */ export type TupleLength = T["length"] /** * @description Get the first index of a value in a tuple. * * @example * ``` * // Expect: 1 * type Example1 = TupleIndexOf<[1, 2, 3], 2> * // Expect: -1 * type Example2 = TupleIndexOf<[1, 2, 3], 4> * ``` */ export type TupleIndexOf = InternalTupleIndexCounter type InternalTupleLastIndexCounter< T extends readonly unknown[], U, Count extends readonly unknown[] = [], Last extends number = -1, > = T extends readonly [infer First, ...infer Rest] ? InternalTupleLastIndexCounter< Rest, U, [...Count, unknown], InternalIsEqual extends true ? Count["length"] : Last > : Last /** * @description Get the last index of a value in a tuple. * * @example * ``` * // Expect: 2 * type Example1 = TupleLastIndexOf<[1, 2, 1], 1> * // Expect: -1 * type Example2 = TupleLastIndexOf<[1, 2, 3], 4> * ``` */ export type TupleLastIndexOf = InternalTupleLastIndexCounter /** * @description Count occurrences of a value in a tuple. * * @example * ``` * // Expect: 2 * type Example1 = TupleCount<[1, 2, 1], 1> * // Expect: 0 * type Example2 = TupleCount<[1, 2, 3], 4> * ``` */ export type TupleCount< T extends readonly unknown[], U, Acc extends readonly unknown[] = [], > = T extends readonly [infer First, ...infer Rest] ? InternalIsEqual extends true ? TupleCount : TupleCount : Acc["length"] /** * @description Find the first index of an element that extends a predicate type. * * @example * ``` * // Expect: 1 * type Example1 = TupleFindIndex<[1, 'a', true], string> * // Expect: -1 * type Example2 = TupleFindIndex<[1, 2], string> * ``` */ export type TupleFindIndex< T extends readonly unknown[], P, Count extends readonly unknown[] = [], > = T extends readonly [infer First, ...infer Rest] ? First extends P ? Count["length"] : TupleFindIndex : -1 /** * @description Get the head index (0 for non-empty tuples). * * @example * ``` * // Expect: 0 * type Example1 = TupleHeadIndex<[1, 2]> * // Expect: never * type Example2 = TupleHeadIndex<[]> * ``` */ export type TupleHeadIndex = T extends [] ? never : 0 /** * @description Get the last index of a tuple. * * @example * ``` * // Expect: 2 * type Example1 = TupleLastIndex<[1, 2, 3]> * // Expect: never * type Example2 = TupleLastIndex<[]> * ``` */ export type TupleLastIndex = T extends [] ? never : InternalTupleBuildArray extends [unknown, ...infer Rest] ? Rest["length"] : never /** * @description Get the index of the minimum numeric literal in a tuple of numbers. * * @example * ``` * // Expect: 1 * type Example1 = TupleMinIndex<[3, 1, 2]> * // Expect: 0 * type Example2 = TupleMinIndex<[1]> * ``` */ export type TupleMinIndex< T extends readonly number[], Count extends readonly unknown[] = [], MinIndex extends number = 0, MinValue extends number | null = null, > = T extends readonly [infer First extends number, ...infer Rest extends number[]] ? MinValue extends null ? TupleMinIndex : MinValue extends number ? InternalTupleBuildArray extends [...InternalTupleBuildArray, ...infer _] ? TupleMinIndex : TupleMinIndex : MinIndex : MinIndex /** * @description Get the index of the maximum numeric literal in a tuple of numbers. * * @example * ``` * // Expect: 0 * type Example1 = TupleMaxIndex<[3, 1, 2]> * // Expect: 0 * type Example2 = TupleMaxIndex<[1]> * ``` */ export type TupleMaxIndex< T extends readonly number[], Count extends readonly unknown[] = [], MaxIndex extends number = 0, MaxValue extends number | null = null, > = T extends readonly [infer First extends number, ...infer Rest extends number[]] ? MaxValue extends null ? TupleMaxIndex : MaxValue extends number ? InternalTupleBuildArray extends [...InternalTupleBuildArray, ...infer _] ? TupleMaxIndex : TupleMaxIndex : MaxIndex : MaxIndex /** * @description Find the first element that extends a predicate type. * * @example * ``` * // Expect: 'a' * type Example1 = TupleFind<[1, 'a', true], string> * // Expect: never * type Example2 = TupleFind<[1, 2], string> * ``` */ export type TupleFind = T extends readonly [ infer First, ...infer Rest, ] ? First extends P ? First : TupleFind : never /** * @description Check if a tuple has duplicate elements. * * @example * ``` * // Expect: true * type Example1 = TupleHasDuplicates<[1, 2, 1]> * // Expect: false * type Example2 = TupleHasDuplicates<[1, 2, 3]> * ``` */ export type TupleHasDuplicates = T extends readonly [ infer First, ...infer Rest, ] ? TupleIncludes extends true ? true : TupleHasDuplicates : false /** * @description Get all indices where a value appears in a tuple. * * @example * ``` * // Expect: [0, 2] * type Example1 = TupleIndicesOf<[1, 2, 1], 1> * // Expect: [] * type Example2 = TupleIndicesOf<[1, 2, 3], 4> * ``` */ export type TupleIndicesOf< T extends readonly unknown[], U, Count extends readonly unknown[] = [], Acc extends readonly number[] = [], > = T extends readonly [infer First, ...infer Rest] ? InternalIsEqual extends true ? TupleIndicesOf : TupleIndicesOf : Acc /** * @description Alias of TupleIndexOf. * * @example * ``` * // Expect: 0 * type Example1 = TupleFirstIndexOf<[1, 2], 1> * // Expect: -1 * type Example2 = TupleFirstIndexOf<[1, 2], 3> * ``` */ export type TupleFirstIndexOf = TupleIndexOf /** * @description Get the last index for each element in the tuple. * * @example * ``` * // Expect: [2, 1, 2] * type Example1 = TupleLastIndexOfAll<[1, 2, 1]> * // Expect: [] * type Example2 = TupleLastIndexOfAll<[]> * ``` */ export type TupleLastIndexOfAll = T extends readonly [ infer First, ...infer Rest, ] ? [TupleLastIndexOf, ...TupleLastIndexOfAll] : [] type InternalTupleFindLastIndex< T extends readonly unknown[], P, Count extends readonly unknown[] = [], Last extends number = -1, > = T extends readonly [infer First, ...infer Rest] ? InternalTupleFindLastIndex< Rest, P, [...Count, unknown], First extends P ? Count["length"] : Last > : Last /** * @description Find the last index of an element that extends a predicate type. * * @example * ``` * // Expect: 2 * type Example1 = TupleFindLastIndex<[1, 'a', 'b'], string> * // Expect: -1 * type Example2 = TupleFindLastIndex<[1, 2], string> * ``` */ export type TupleFindLastIndex = InternalTupleFindLastIndex // ============================================================================ // Generation // ============================================================================ type InternalAdd = [ ...InternalTupleBuildArray, ...InternalTupleBuildArray, ]["length"] type InternalSubtract = InternalTupleBuildArray extends [...infer Rest, ...InternalTupleBuildArray] ? Rest["length"] : never type InternalTupleRepeat< T, N extends number, Acc extends readonly unknown[] = [], > = Acc["length"] extends N ? Acc : InternalTupleRepeat /** * @description Repeat an element type N times. * * @example * ``` * // Expect: [string, string, string] * type Example1 = TupleRepeat * // Expect: [] * type Example2 = TupleRepeat * ``` */ export type TupleRepeat = InternalTupleRepeat /** * @description Create a numeric range tuple from Start to End (inclusive). * * @example * ``` * // Expect: [1, 2, 3] * type Example1 = TupleRange<1, 3> * // Expect: [0] * type Example2 = TupleRange<0, 0> * ``` */ export type TupleRange< Start extends number, End extends number, Acc extends readonly number[] = [], Current extends number = Start, > = InternalTupleBuildArray extends [...InternalTupleBuildArray, ...infer _] ? InternalIsEqual extends true ? [...Acc, Current] : TupleRange< Start, End, [...Acc, Current], InternalAdd extends number ? InternalAdd : never > : Acc /** * @description Fill a tuple of length N with element type T. * * @example * ``` * // Expect: [number, number] * type Example1 = TupleFill * // Expect: [] * type Example2 = TupleFill * ``` */ export type TupleFill = TupleRepeat /** * @description Build a tuple of length N from element type T. * * @example * ``` * // Expect: [boolean, boolean] * type Example1 = TupleOf * // Expect: [] * type Example2 = TupleOf * ``` */ export type TupleOf = TupleRepeat /** * @description Alias of TupleOf. * * @example * ``` * // Expect: [1, 1] * type Example1 = TupleMake<1, 2> * // Expect: [] * type Example2 = TupleMake * ``` */ export type TupleMake = TupleOf /** * @description Pad a tuple at the start to length N. * * @example * ``` * // Expect: [0, 1, 2] * type Example1 = TuplePadStart<[1, 2], 3, 0> * // Expect: [1] * type Example2 = TuplePadStart<[1], 1, 0> * ``` */ export type TuplePadStart = TupleLength extends N ? T : TupleLength extends infer L ? L extends number ? InternalTupleBuildArray extends [...InternalTupleBuildArray, ...infer _] ? T : TuplePadStart<[Fill, ...T], N, Fill> : T : T /** * @description Pad a tuple at the end to length N. * * @example * ``` * // Expect: [1, 2, 0] * type Example1 = TuplePadEnd<[1, 2], 3, 0> * // Expect: [1] * type Example2 = TuplePadEnd<[1], 1, 0> * ``` */ export type TuplePadEnd = TupleLength extends N ? T : TupleLength extends infer L ? L extends number ? InternalTupleBuildArray extends [...InternalTupleBuildArray, ...infer _] ? T : TuplePadEnd<[...T, Fill], N, Fill> : T : T type InternalInsertEach = P extends readonly [ infer First, ...infer Rest, ] ? [T, First, ...Rest] | [First, ...InternalInsertEach] : [T] /** * @description Get all permutations of a tuple as a union of tuples. * * @example * ``` * // Expect: [1, 2] | [2, 1] * type Example1 = TuplePermutations<[1, 2]> * // Expect: [] * type Example2 = TuplePermutations<[]> * ``` */ export type TuplePermutations = T extends [] ? [] : T extends readonly [infer First, ...infer Rest] ? TuplePermutations extends infer Perm ? Perm extends readonly unknown[] ? InternalInsertEach : never : never : never /** * @description Get all combinations of a tuple as a union of tuples. * * @example * ``` * // Expect: [] | [1] | [2] | [1, 2] * type Example1 = TupleCombinations<[1, 2]> * // Expect: [] * type Example2 = TupleCombinations<[]> * ``` */ export type TupleCombinations = T extends readonly [ infer First, ...infer Rest, ] ? TupleCombinations extends infer Comb ? Comb extends readonly unknown[] ? Comb | [First, ...Comb] : never : never : [] /** * @description Compute the cartesian product of two tuples as a union of pairs. * * @example * ``` * // Expect: [1, 'a'] | [1, 'b'] | [2, 'a'] | [2, 'b'] * type Example1 = TupleCartesian<[1, 2], ['a', 'b']> * // Expect: never * type Example2 = TupleCartesian<[], ['a']> * ``` */ export type TupleCartesian< A extends readonly unknown[], B extends readonly unknown[], > = A extends readonly [infer First, ...infer Rest] ? B extends readonly unknown[] ? B[number] extends infer Item ? [First, Item] | TupleCartesian : never : never : never /** * @description Get the power set of a tuple as a union of tuples. * * @example * ``` * // Expect: [] | [1] | [2] | [1, 2] * type Example1 = TuplePowerSet<[1, 2]> * // Expect: [] * type Example2 = TuplePowerSet<[]> * ``` */ export type TuplePowerSet = TupleCombinations /** * @description Intersperse a separator between tuple elements. * * @example * ``` * // Expect: [1, 0, 2, 0, 3] * type Example1 = TupleIntersperse<[1, 2, 3], 0> * // Expect: [] * type Example2 = TupleIntersperse<[], 0> * ``` */ export type TupleIntersperse = T extends readonly [ infer First, ...infer Rest, ] ? Rest extends [] ? [First] : [First, S, ...TupleIntersperse] : [] /** * @description Repeat each element N times. * * @example * ``` * // Expect: [1, 1, 2, 2] * type Example1 = TupleRepeatEach<[1, 2], 2> * // Expect: [] * type Example2 = TupleRepeatEach<[], 3> * ``` */ export type TupleRepeatEach = T extends readonly [ infer First, ...infer Rest, ] ? [...TupleRepeat, ...TupleRepeatEach] : [] /** * @description Create a numeric range tuple from Start to End with step. * * @example * ``` * // Expect: [1, 3, 5] * type Example1 = TupleRangeStep<1, 5, 2> * // Expect: [0] * type Example2 = TupleRangeStep<0, 0, 1> * ``` */ export type TupleRangeStep< Start extends number, End extends number, Step extends number, Acc extends readonly number[] = [], Current extends number = Start, > = InternalTupleBuildArray extends [...InternalTupleBuildArray, ...infer _] ? InternalIsEqual extends true ? [...Acc, Current] : TupleRangeStep< Start, End, Step, [...Acc, Current], InternalAdd extends number ? InternalAdd : never > : Acc // ============================================================================ // Extraction // ============================================================================ /** * @description Extract the type of the first element in a tuple. * * @example * ``` * // Expect: number * type Example1 = TupleHead<[number, string, boolean]> * // Expect: string * type Example2 = TupleHead<[string]> * ``` */ export type TupleHead = T extends readonly [infer First, ...unknown[]] ? First : never /** * @description Extract the last element from a tuple. * * @example * ``` * // Expect: boolean * type Example1 = TupleLast<[number, string, boolean]> * // Expect: string * type Example2 = TupleLast<[string]> * ``` */ export type TupleLast = T extends readonly [...unknown[], infer Last] ? Last : never /** * @description Extract all elements except the first one from a tuple. * * @example * ``` * // Expect: [string, boolean] * type Example1 = TupleTail<[number, string, boolean]> * // Expect: [] * type Example2 = TupleTail<[string]> * ``` */ export type TupleTail = T extends readonly [unknown, ...infer Rest] ? Rest : [] /** * @description Extract all elements except the last one from a tuple. * * @example * ``` * // Expect: [number, string] * type Example1 = TuplePrev<[number, string, boolean]> * // Expect: [] * type Example2 = TuplePrev<[string]> * ``` */ export type TuplePrev = T extends readonly [...infer Rest, unknown] ? Rest : [] type InternalAt< T extends readonly unknown[], N extends number, Count extends readonly unknown[] = [], > = Count["length"] extends N ? TupleHead : InternalAt, N, [...Count, unknown]> /** * @description Get the element at index N in a tuple. * * @example * ``` * // Expect: number * type Example1 = TupleAt<[number, string, boolean], 0> * // Expect: boolean * type Example2 = TupleAt<[number, string, boolean], 2> * ``` */ export type TupleAt = InternalAt /** * @description Take the first N elements from a tuple. * * @example * ``` * // Expect: [1, 2] * type Example1 = TupleTake<[1, 2, 3], 2> * // Expect: [] * type Example2 = TupleTake<[1, 2], 0> * ``` */ export type TupleTake< T extends readonly unknown[], N extends number, Acc extends readonly unknown[] = [], > = Acc["length"] extends N ? Acc : T extends readonly [infer First, ...infer Rest] ? TupleTake : Acc /** * @description Take the last N elements from a tuple. * * @example * ``` * // Expect: [2, 3] * type Example1 = TupleTakeLast<[1, 2, 3], 2> * // Expect: [] * type Example2 = TupleTakeLast<[1, 2], 0> * ``` */ export type TupleTakeLast = TupleReverse< TupleTake, N> > type InternalTupleSliceHelper< T extends readonly unknown[], Start extends number, End extends number, > = TupleTake, InternalSubtract> /** * @description Slice a tuple from Start (inclusive) to End (exclusive). * * @example * ``` * // Expect: [2, 3] * type Example1 = TupleSlice<[1, 2, 3, 4], 1, 3> * // Expect: [] * type Example2 = TupleSlice<[1, 2], 1, 1> * ``` */ export type TupleSlice< T extends readonly unknown[], Start extends number, End extends number, > = InternalTupleSliceHelper /** * @description Drop the first N elements from a tuple. * * @example * ``` * // Expect: [3] * type Example1 = TupleDrop<[1, 2, 3], 2> * // Expect: [] * type Example2 = TupleDrop<[1, 2], 2> * ``` */ export type TupleDrop< T extends readonly unknown[], N extends number, Count extends readonly unknown[] = [], > = Count["length"] extends N ? T : T extends readonly [unknown, ...infer Rest] ? TupleDrop : [] /** * @description Drop the last N elements from a tuple. * * @example * ``` * // Expect: [1] * type Example1 = TupleDropLast<[1, 2, 3], 2> * // Expect: [] * type Example2 = TupleDropLast<[1, 2], 2> * ``` */ export type TupleDropLast = TupleReverse< TupleDrop, N> > /** * @description Split a tuple at index N into [left, right]. * * @example * ``` * // Expect: [[1, 2], [3, 4]] * type Example1 = TupleSplitAt<[1, 2, 3, 4], 2> * // Expect: [[], [1]] * type Example2 = TupleSplitAt<[1], 0> * ``` */ export type TupleSplitAt = [ TupleTake, TupleDrop, ] /** * @description Pick elements by index list. * * @example * ``` * // Expect: [1, 3] * type Example1 = TuplePick<[1, 2, 3], [0, 2]> * // Expect: [] * type Example2 = TuplePick<[1, 2], []> * ``` */ export type TuplePick< T extends readonly unknown[], I extends readonly number[], > = I extends readonly [infer Index extends number, ...infer Rest extends number[]] ? [TupleAt, ...TuplePick] : [] /** * @description Omit elements by index list. * * @example * ``` * // Expect: [2] * type Example1 = TupleOmit<[1, 2, 3], [0, 2]> * // Expect: [1, 2] * type Example2 = TupleOmit<[1, 2], []> * ``` */ export type TupleOmit< T extends readonly unknown[], I extends readonly number[], Count extends readonly unknown[] = [], Acc extends readonly unknown[] = [], > = T extends readonly [infer First, ...infer Rest] ? TupleIncludes extends true ? TupleOmit : TupleOmit : Acc /** * @description Partition a tuple into [matching, rest] by predicate type. * * @example * ``` * // Expect: [[1, 2], ['a']] * type Example1 = TuplePartition<[1, 'a', 2], number> * // Expect: [[], [1, 2]] * type Example2 = TuplePartition<[1, 2], string> * ``` */ export type TuplePartition< T extends readonly unknown[], P, Matches extends readonly unknown[] = [], Rest extends readonly unknown[] = [], > = T extends readonly [infer First, ...infer Tail] ? First extends P ? TuplePartition : TuplePartition : [Matches, Rest] /** * @description Group a tuple of [key, value] pairs by key. * * @example * ``` * // Expect: { a: [1, 3]; b: [2] } * type Example1 = TupleGroupBy<[['a', 1], ['b', 2], ['a', 3]]> * // Expect: {} * type Example2 = TupleGroupBy<[]> * ``` */ export type TupleGroupBy< T extends ReadonlyArray, Acc extends Record = Record, > = T extends readonly [ infer First extends readonly [PropertyKey, unknown], ...infer Rest extends ReadonlyArray, ] ? TupleGroupBy< Rest, { [K in keyof Acc | First[0]]: K extends First[0] ? K extends keyof Acc ? [...Acc[K], First[1]] : [First[1]] : K extends keyof Acc ? Acc[K] : never } > : Acc /** * @description Create a sliding window of size N. * * @example * ``` * // Expect: [[1, 2], [2, 3]] * type Example1 = TupleWindow<[1, 2, 3], 2> * // Expect: [] * type Example2 = TupleWindow<[1], 2> * ``` */ export type TupleWindow = TupleTake extends infer Head ? Head extends readonly unknown[] ? TupleLength extends N ? [Head, ...TupleWindow, N>] : [] : [] : [] /** * @description Pluck a property from a tuple of objects. * * @example * ``` * // Expect: [1, 2] * type Example1 = TuplePluck<[{ id: 1 }, { id: 2 }], 'id'> * // Expect: [] * type Example2 = TuplePluck<[], 'id'> * ``` */ export type TuplePluck = T extends readonly [ infer First, ...infer Rest, ] ? [First extends Record ? First[K] : never, ...TuplePluck] : [] /** * @description Alias of TuplePick. * * @example * ``` * // Expect: [1] * type Example1 = TuplePickByIndex<[1, 2], [0]> * // Expect: [] * type Example2 = TuplePickByIndex<[1, 2], []> * ``` */ export type TuplePickByIndex = TuplePick< T, I > /** * @description Alias of TupleOmit. * * @example * ``` * // Expect: [2] * type Example1 = TupleOmitByIndex<[1, 2], [0]> * // Expect: [1, 2] * type Example2 = TupleOmitByIndex<[1, 2], []> * ``` */ export type TupleOmitByIndex = TupleOmit< T, I > type InternalTupleSplitHelper< T extends readonly unknown[], Sep, Current extends readonly unknown[] = [], Acc extends readonly unknown[] = [], > = T extends readonly [infer First, ...infer Rest] ? InternalIsEqual extends true ? InternalTupleSplitHelper : InternalTupleSplitHelper : [...Acc, Current] /** * @description Split a tuple by a separator element. * * @example * ``` * // Expect: [[1], [2, 3]] * type Example1 = TupleSplitBy<[1, 0, 2, 3], 0> * // Expect: [[]] * type Example2 = TupleSplitBy<[], 0> * ``` */ export type TupleSplitBy = InternalTupleSplitHelper /** * @description Chunk a tuple by a separator element. * * @example * ``` * // Expect: [[1], [2, 3]] * type Example1 = TupleChunkBy<[1, 0, 2, 3], 0> * // Expect: [[]] * type Example2 = TupleChunkBy<[], 0> * ``` */ export type TupleChunkBy = TupleSplitBy // ============================================================================ // Manipulation // ============================================================================ /** * @description Prepend an element to a tuple. * * @example * ``` * // Expect: [number, string, boolean] * type Example1 = TuplePrepend<[string, boolean], number> * // Expect: [number] * type Example2 = TuplePrepend<[], number> * ``` */ export type TuplePrepend = [E, ...T] /** * @description Append an element to a tuple. * * @example * ``` * // Expect: [string, boolean, number] * type Example1 = TupleAppend<[string, boolean], number> * // Expect: [number] * type Example2 = TupleAppend<[], number> * ``` */ export type TupleAppend = [...T, E] type InternalReverse< T extends readonly unknown[], Acc extends readonly unknown[] = [], > = T extends readonly [infer First, ...infer Rest] ? InternalReverse : Acc /** * @description Reverse the order of elements in a tuple. * * @example * ``` * // Expect: [boolean, string, number] * type Example1 = TupleReverse<[number, string, boolean]> * // Expect: [] * type Example2 = TupleReverse<[]> * ``` */ export type TupleReverse = InternalReverse /** * @description Concatenate two tuples. * * @example * ``` * // Expect: [1, 2, 3] * type Example1 = TupleConcat<[1, 2], [3]> * // Expect: [1] * type Example2 = TupleConcat<[1], []> * ``` */ export type TupleConcat = [...A, ...B] /** * @description Flatten a tuple by one level. * * @example * ``` * // Expect: [1, 2, 3] * type Example1 = TupleFlatten<[[1, 2], [3]]> * // Expect: [1, 2] * type Example2 = TupleFlatten<[1, [2]]> * ``` */ export type TupleFlatten = T extends readonly [ infer First, ...infer Rest, ] ? First extends readonly unknown[] ? [...First, ...TupleFlatten] : [First, ...TupleFlatten] : [] /** * @description Prepend an element to each tuple in a tuple of tuples. * * @example * ``` * // Expect: [[0, 1], [0, 2]] * type Example1 = TuplePrependAll<[[1], [2]], 0> * // Expect: [] * type Example2 = TuplePrependAll<[], 0> * ``` */ export type TuplePrependAll = T extends readonly [ infer First extends readonly unknown[], ...infer Rest extends readonly unknown[][], ] ? [[E, ...First], ...TuplePrependAll] : [] /** * @description Append an element to each tuple in a tuple of tuples. * * @example * ``` * // Expect: [[1, 0], [2, 0]] * type Example1 = TupleAppendAll<[[1], [2]], 0> * // Expect: [] * type Example2 = TupleAppendAll<[], 0> * ``` */ export type TupleAppendAll = T extends readonly [ infer First extends readonly unknown[], ...infer Rest extends readonly unknown[][], ] ? [[...First, E], ...TupleAppendAll] : [] /** * @description Map a tuple using a mapper function type. * * @example * ``` * // Expect: [string, string] * type Example1 = TupleMap<[1, 2], (value: number) => string> * // Expect: [] * type Example2 = TupleMap<[], (value: number) => string> * ``` */ export type TupleMap< T extends readonly unknown[], Mapper extends (value: unknown, index: number, tuple: readonly unknown[]) => unknown, > = { [K in keyof T]: Mapper extends (value: T[K], index: number, tuple: T) => infer R ? R : never } /** * @description Filter a tuple by a predicate type. * * @example * ``` * // Expect: [1, 2] * type Example1 = TupleFilter<[1, 'a', 2], number> * // Expect: [] * type Example2 = TupleFilter<[true, false], string> * ``` */ export type TupleFilter< T extends readonly unknown[], P, Acc extends readonly unknown[] = [], > = T extends readonly [infer First, ...infer Rest] ? First extends P ? TupleFilter : TupleFilter : Acc type InternalTupleZipHelper< A extends readonly unknown[], B extends readonly unknown[], > = A extends readonly [infer FirstA, ...infer RestA] ? B extends readonly [infer FirstB, ...infer RestB] ? [[FirstA, FirstB], ...InternalTupleZipHelper] : [] : [] /** * @description Zip two tuples into a tuple of pairs. * * @example * ``` * // Expect: [[1, 'a'], [2, 'b']] * type Example1 = TupleZip<[1, 2], ['a', 'b']> * // Expect: [] * type Example2 = TupleZip<[], ['a']> * ``` */ export type TupleZip< A extends readonly unknown[], B extends readonly unknown[], > = InternalTupleZipHelper type InternalTupleUnzipHelper< T extends readonly unknown[], Left extends readonly unknown[] = [], Right extends readonly unknown[] = [], > = T extends readonly [infer First, ...infer Rest] ? First extends readonly [infer L, infer R] ? InternalTupleUnzipHelper : InternalTupleUnzipHelper : [Left, Right] /** * @description Unzip a tuple of pairs into two tuples. * * @example * ``` * // Expect: [[1, 2], ['a', 'b']] * type Example1 = TupleUnzip<[[1, 'a'], [2, 'b']]> * // Expect: [[], []] * type Example2 = TupleUnzip<[]> * ``` */ export type TupleUnzip = InternalTupleUnzipHelper type InternalTupleDedup< T extends readonly unknown[], Acc extends readonly unknown[] = [], > = T extends readonly [infer First, ...infer Rest] ? TupleIncludes extends true ? InternalTupleDedup : InternalTupleDedup : Acc /** * @description Remove duplicate elements from a tuple. * * @example * ``` * // Expect: [1, 2] * type Example1 = TupleUnique<[1, 2, 1]> * // Expect: [] * type Example2 = TupleUnique<[]> * ``` */ export type TupleUnique = InternalTupleDedup /** * @description Swap two elements by index. * * @example * ``` * // Expect: [2, 1, 3] * type Example1 = TupleSwap<[1, 2, 3], 0, 1> * // Expect: [1, 2, 3] * type Example2 = TupleSwap<[1, 2, 3], 0, 0> * ``` */ export type TupleSwap< T extends readonly unknown[], A extends number, B extends number, Count extends readonly unknown[] = [], Acc extends readonly unknown[] = [], > = T extends readonly [infer First, ...infer Rest] ? Count["length"] extends A ? TupleSwap]> : Count["length"] extends B ? TupleSwap]> : TupleSwap : Acc /** * @description Insert a value at index N. * * @example * ``` * // Expect: [1, 0, 2] * type Example1 = TupleInsert<[1, 2], 1, 0> * // Expect: [0, 1] * type Example2 = TupleInsert<[1], 0, 0> * ``` */ export type TupleInsert< T extends readonly unknown[], N extends number, V, Acc extends readonly unknown[] = [], > = Acc["length"] extends N ? [...Acc, V, ...T] : T extends readonly [infer First, ...infer Rest] ? TupleInsert : [...Acc, V] /** * @description Remove the element at index N. * * @example * ``` * // Expect: [1, 3] * type Example1 = TupleRemoveAt<[1, 2, 3], 1> * // Expect: [2] * type Example2 = TupleRemoveAt<[2], 0> * ``` */ export type TupleRemoveAt< T extends readonly unknown[], N extends number, Count extends readonly unknown[] = [], Acc extends readonly unknown[] = [], > = T extends readonly [infer First, ...infer Rest] ? Count["length"] extends N ? [...Acc, ...Rest] : TupleRemoveAt : Acc /** * @description Replace the element at index N. * * @example * ``` * // Expect: [1, 0, 3] * type Example1 = TupleReplaceAt<[1, 2, 3], 1, 0> * // Expect: [0] * type Example2 = TupleReplaceAt<[2], 0, 0> * ``` */ export type TupleReplaceAt< T extends readonly unknown[], N extends number, V, Count extends readonly unknown[] = [], Acc extends readonly unknown[] = [], > = T extends readonly [infer First, ...infer Rest] ? Count["length"] extends N ? [...Acc, V, ...Rest] : TupleReplaceAt : Acc type InternalTupleRotateHelper = N extends 0 ? T : InternalTupleRotateHelper, [TupleHead]>, InternalSubtract> /** * @description Rotate a tuple left by N (negative rotates right). * * @example * ``` * // Expect: [2, 3, 1] * type Example1 = TupleRotate<[1, 2, 3], 1> * // Expect: [3, 1, 2] * type Example2 = TupleRotate<[1, 2, 3], -1> * ``` */ export type TupleRotate< T extends readonly unknown[], N extends number, > = `${N}` extends `-${infer P extends number}` ? TupleRotateRight : InternalTupleRotateHelper type InternalTupleChunkHelper< T extends readonly unknown[], N extends number, Current extends readonly unknown[] = [], Acc extends readonly unknown[] = [], > = T extends readonly [infer First, ...infer Rest] ? Current["length"] extends N ? InternalTupleChunkHelper : InternalTupleChunkHelper : Current extends [] ? Acc : [...Acc, Current] /** * @description Chunk a tuple into sub-tuples of size N. * * @example * ``` * // Expect: [[1, 2], [3]] * type Example1 = TupleChunk<[1, 2, 3], 2> * // Expect: [] * type Example2 = TupleChunk<[], 2> * ``` */ export type TupleChunk = InternalTupleChunkHelper< T, N > /** * @description Remove the first element of a tuple. * * @example * ``` * // Expect: [2, 3] * type Example1 = TupleShift<[1, 2, 3]> * // Expect: [] * type Example2 = TupleShift<[1]> * ``` */ export type TupleShift = TupleTail /** * @description Remove the last element of a tuple. * * @example * ``` * // Expect: [1, 2] * type Example1 = TuplePop<[1, 2, 3]> * // Expect: [] * type Example2 = TuplePop<[1]> * ``` */ export type TuplePop = TuplePrev /** * @description Append a value to a tuple. * * @example * ``` * // Expect: [1, 2, 3] * type Example1 = TuplePush<[1, 2], 3> * // Expect: [1] * type Example2 = TuplePush<[], 1> * ``` */ export type TuplePush = TupleAppend /** * @description Prepend a value to a tuple. * * @example * ``` * // Expect: [0, 1, 2] * type Example1 = TupleUnshift<[1, 2], 0> * // Expect: [1] * type Example2 = TupleUnshift<[], 1> * ``` */ export type TupleUnshift = TuplePrepend /** * @description Reverse a section of a tuple from Start to End (exclusive). * * @example * ``` * // Expect: [1, 3, 2, 4] * type Example1 = TupleReverseSection<[1, 2, 3, 4], 1, 3> * // Expect: [1, 2] * type Example2 = TupleReverseSection<[1, 2], 0, 1> * ``` */ export type TupleReverseSection< T extends readonly unknown[], Start extends number, End extends number, > = TupleConcat< TupleTake, TupleConcat>, TupleDrop> > /** * @description Shuffle a tuple (returns permutations as a union). * * @example * ``` * // Expect: [1, 2] | [2, 1] * type Example1 = TupleShuffle<[1, 2]> * // Expect: [] * type Example2 = TupleShuffle<[]> * ``` */ export type TupleShuffle = TuplePermutations type InternalInsertSorted = T extends readonly [ infer First extends number, ...infer Rest extends number[], ] ? InternalTupleBuildArray extends [...InternalTupleBuildArray, ...infer _] ? [First, ...InternalInsertSorted] : [V, First, ...Rest] : [V] /** * @description Sort a tuple of numbers in ascending order. * * @example * ``` * // Expect: [1, 2, 3] * type Example1 = TupleSort<[3, 1, 2]> * // Expect: [] * type Example2 = TupleSort<[]> * ``` */ export type TupleSort = T extends readonly [ infer First extends number, ...infer Rest extends number[], ] ? InternalInsertSorted> : [] /** * @description Stable sort a tuple of numbers in ascending order. * * @example * ``` * // Expect: [1, 2, 3] * type Example1 = TupleStableSort<[3, 1, 2]> * // Expect: [] * type Example2 = TupleStableSort<[]> * ``` */ export type TupleStableSort = TupleSort /** * @description Flatten a tuple by one level. * * @example * ``` * // Expect: [1, 2] * type Example1 = TupleFlattenOnce<[[1], [2]]> * // Expect: [] * type Example2 = TupleFlattenOnce<[]> * ``` */ export type TupleFlattenOnce = TupleFlatten /** * @description Deeply flatten a tuple. * * @example * ``` * // Expect: [1, 2, 3] * type Example1 = TupleFlattenDeep<[[1, [2]], 3]> * // Expect: [] * type Example2 = TupleFlattenDeep<[]> * ``` */ export type TupleFlattenDeep = T extends readonly [ infer First, ...infer Rest, ] ? First extends readonly unknown[] ? [...TupleFlattenDeep, ...TupleFlattenDeep] : [First, ...TupleFlattenDeep] : [] /** * @description Remove falsy values from a tuple. * * @example * ``` * // Expect: [1, 'a'] * type Example1 = TupleCompact<[0, 1, '', 'a', false]> * // Expect: [] * type Example2 = TupleCompact<[]> * ``` */ export type TupleCompact< T extends readonly unknown[], Acc extends readonly unknown[] = [], > = T extends readonly [infer First, ...infer Rest] ? First extends false | 0 | "" | null | undefined ? TupleCompact : TupleCompact : Acc /** * @description Get elements in A that are also in B. * * @example * ``` * // Expect: [2] * type Example1 = TupleIntersect<[1, 2, 3], [2, 4]> * // Expect: [] * type Example2 = TupleIntersect<[1], [2]> * ``` */ export type TupleIntersect< A extends readonly unknown[], B extends readonly unknown[], Acc extends readonly unknown[] = [], > = A extends readonly [infer First, ...infer Rest] ? TupleIncludes extends true ? TupleIntersect : TupleIntersect : Acc /** * @description Get elements in A that are not in B. * * @example * ``` * // Expect: [1, 3] * type Example1 = TupleDifference<[1, 2, 3], [2]> * // Expect: [1] * type Example2 = TupleDifference<[1], [2]> * ``` */ export type TupleDifference< A extends readonly unknown[], B extends readonly unknown[], Acc extends readonly unknown[] = [], > = A extends readonly [infer First, ...infer Rest] ? TupleIncludes extends true ? TupleDifference : TupleDifference : Acc /** * @description Get elements that are in A or B but not both. * * @example * ``` * // Expect: [1, 3] * type Example1 = TupleSymmetricDifference<[1, 2], [2, 3]> * // Expect: [1] * type Example2 = TupleSymmetricDifference<[1], []> * ``` */ export type TupleSymmetricDifference< A extends readonly unknown[], B extends readonly unknown[], > = TupleConcat, TupleDifference> /** * @description Reverse all but the last element of a tuple. * * @example * ``` * // Expect: [2, 1, 3] * type Example1 = TupleReverseHead<[1, 2, 3]> * // Expect: [] * type Example2 = TupleReverseHead<[]> * ``` */ export type TupleReverseHead = T extends readonly [ ...infer Rest, infer Last, ] ? [...TupleReverse, Last] : [] /** * @description Reverse all but the first element of a tuple. * * @example * ``` * // Expect: [1, 3, 2] * type Example1 = TupleReverseTail<[1, 2, 3]> * // Expect: [] * type Example2 = TupleReverseTail<[]> * ``` */ export type TupleReverseTail = T extends readonly [ infer First, ...infer Rest, ] ? [First, ...TupleReverse] : [] type InternalTupleRotateLeft = N extends 0 ? T : InternalTupleRotateLeft, [TupleHead]>, InternalSubtract> /** * @description Rotate a tuple left by N. * * @example * ``` * // Expect: [2, 3, 1] * type Example1 = TupleRotateLeft<[1, 2, 3], 1> * // Expect: [1, 2] * type Example2 = TupleRotateLeft<[1, 2], 0> * ``` */ export type TupleRotateLeft< T extends readonly unknown[], N extends number = 1, > = InternalTupleRotateLeft type InternalTupleRotateRight = N extends 0 ? T : InternalTupleRotateRight], TuplePrev>, InternalSubtract> /** * @description Rotate a tuple right by N. * * @example * ``` * // Expect: [3, 1, 2] * type Example1 = TupleRotateRight<[1, 2, 3], 1> * // Expect: [1, 2] * type Example2 = TupleRotateRight<[1, 2], 0> * ``` */ export type TupleRotateRight< T extends readonly unknown[], N extends number = 1, > = InternalTupleRotateRight /** * @description Move an element from index From to index To. * * @example * ``` * // Expect: [2, 3, 1] * type Example1 = TupleMove<[1, 2, 3], 0, 2> * // Expect: [1, 2, 3] * type Example2 = TupleMove<[1, 2, 3], 1, 1> * ``` */ export type TupleMove< T extends readonly unknown[], From extends number, To extends number, > = TupleInsert, To, TupleAt> /** * @description Swap each adjacent pair of elements. * * @example * ``` * // Expect: [2, 1, 4, 3] * type Example1 = TupleSwapPairs<[1, 2, 3, 4]> * // Expect: [1] * type Example2 = TupleSwapPairs<[1]> * ``` */ export type TupleSwapPairs = T extends readonly [ infer A, infer B, ...infer Rest, ] ? [B, A, ...TupleSwapPairs] : T /** * @description Interleave two tuples. * * @example * ``` * // Expect: [1, 'a', 2, 'b'] * type Example1 = TupleInterleave<[1, 2], ['a', 'b']> * // Expect: [1] * type Example2 = TupleInterleave<[1], []> * ``` */ export type TupleInterleave< A extends readonly unknown[], B extends readonly unknown[], > = A extends readonly [infer FirstA, ...infer RestA] ? B extends readonly [infer FirstB, ...infer RestB] ? [FirstA, FirstB, ...TupleInterleave] : [FirstA, ...TupleInterleave] : B extends readonly [infer FirstB, ...infer RestB] ? [FirstB, ...TupleInterleave<[], RestB>] : [] type InternalTupleZipLongestHelper< A extends readonly unknown[], B extends readonly unknown[], Fill, > = A extends readonly [infer FirstA, ...infer RestA] ? B extends readonly [infer FirstB, ...infer RestB] ? [[FirstA, FirstB], ...InternalTupleZipLongestHelper] : [[FirstA, Fill], ...InternalTupleZipLongestHelper] : B extends readonly [infer FirstB, ...infer RestB] ? [[Fill, FirstB], ...InternalTupleZipLongestHelper<[], RestB, Fill>] : [] /** * @description Zip two tuples, filling missing entries. * * @example * ``` * // Expect: [[1, 'a'], [2, undefined]] * type Example1 = TupleZipLongest<[1, 2], ['a']> * // Expect: [] * type Example2 = TupleZipLongest<[], []> * ``` */ export type TupleZipLongest< A extends readonly unknown[], B extends readonly unknown[], Fill = undefined, > = InternalTupleZipLongestHelper /** * @description Pad both sides to length N (favoring end for odd remainder). * * @example * ``` * // Expect: [0, 1, 2, 0] * type Example1 = TuplePad<[1, 2], 4, 0> * // Expect: [1] * type Example2 = TuplePad<[1], 1, 0> * ``` */ export type TuplePad< T extends readonly unknown[], N extends number, Fill = undefined, > = TuplePadEnd, N, Fill> type InternalTupleFlattenDepth = Depth extends 0 ? T : T extends readonly [infer First, ...infer Rest] ? First extends readonly unknown[] ? [ ...InternalTupleFlattenDepth>, ...InternalTupleFlattenDepth, ] : [First, ...InternalTupleFlattenDepth] : [] /** * @description Flatten a tuple to a given depth. * * @example * ``` * // Expect: [1, 2, [3]] * type Example1 = TupleFlattenToDepth<[[1], [2, [3]]], 1> * // Expect: [1, 2, 3] * type Example2 = TupleFlattenToDepth<[[1], [2, [3]]], 2> * ``` */ export type TupleFlattenToDepth< T extends readonly unknown[], Depth extends number, > = InternalTupleFlattenDepth // ============================================================================ // Conversion // ============================================================================ /** * @description Convert a tuple to a union of its element types. * * @example * ``` * // Expect: 1 | 2 * type Example1 = TupleToUnion<[1, 2]> * // Expect: never * type Example2 = TupleToUnion<[]> * ``` */ export type TupleToUnion = T[number] /** * @description Convert a tuple of keys to an object with identical values. * * @example * ``` * // Expect: { a: 'a'; b: 'b' } * type Example1 = TupleToObject<['a', 'b']> * // Expect: {} * type Example2 = TupleToObject<[]> * ``` */ export type TupleToObject = { [K in T[number]]: K } /** * @description Convert a tuple of [key, value] pairs to a record. * * @example * ``` * // Expect: { a: 1; b: 2 } * type Example1 = TupleToRecord<[['a', 1], ['b', 2]]> * // Expect: {} * type Example2 = TupleToRecord<[]> * ``` */ export type TupleToRecord> = { [K in T[number] as K extends readonly [infer Key extends PropertyKey, unknown] ? Key : never]: K extends readonly [PropertyKey, infer Value] ? Value : never } /** * @description Join tuple elements into a string with a separator. * * @example * ``` * // Expect: 'a-b' * type Example1 = TupleToString<['a', 'b'], '-'> * // Expect: '' * type Example2 = TupleToString<[], '-'> * ``` */ export type TupleToString< T extends ReadonlyArray, Sep extends string = "", > = T extends readonly [ infer First extends string | number | boolean, ...infer Rest extends Array, ] ? Rest extends [] ? `${First}` : `${First}${Sep}${TupleToString}` : "" /** * @description Convert a tuple to an array of its element union. * * @example * ``` * // Expect: Array<1 | 2> * type Example1 = TupleToArray<[1, 2]> * // Expect: Array * type Example2 = TupleToArray<[]> * ``` */ export type TupleToArray = Array type InternalUnionToIntersection = (U extends unknown ? (value: U) => void : never) extends ( value: infer I, ) => void ? I : never /** * @description Convert a tuple to an intersection of its elements. * * @example * ``` * // Expect: { a: 1 } & { b: 2 } * type Example1 = TupleToIntersection<[{ a: 1 }, { b: 2 }]> * // Expect: unknown * type Example2 = TupleToIntersection<[]> * ``` */ export type TupleToIntersection = InternalUnionToIntersection extends infer R ? R extends unknown ? R : unknown : unknown /** * @description Convert a tuple of [key, value] pairs to a Map type. * * @example * ``` * // Expect: Map<'a' | 'b', 1 | 2> * type Example1 = TupleToMap<[['a', 1], ['b', 2]]> * // Expect: Map * type Example2 = TupleToMap<[]> * ``` */ export type TupleToMap> = Map< T[number] extends readonly [infer Key extends PropertyKey, unknown] ? Key : never, T[number] extends readonly [PropertyKey, infer Value] ? Value : never > /** * @description Convert a tuple to a Set type. * * @example * ``` * // Expect: Set<1 | 2> * type Example1 = TupleToSet<[1, 2]> * // Expect: Set * type Example2 = TupleToSet<[]> * ``` */ export type TupleToSet = Set /** * @description Make all tuple elements optional. * * @example * ``` * // Expect: [number?, string?] * type Example1 = TupleToOptional<[number, string]> * // Expect: [] * type Example2 = TupleToOptional<[]> * ``` */ export type TupleToOptional = { [K in keyof T]?: T[K] } /** * @description Make all tuple elements required. * * @example * ``` * // Expect: [number, string] * type Example1 = TupleToRequired<[number?, string?]> * // Expect: [] * type Example2 = TupleToRequired<[]> * ``` */ export type TupleToRequired = { [K in keyof T]-?: T[K] } /** * @description Convert a tuple to function parameters (identity). * * @example * ``` * // Expect: [number, string] * type Example1 = TupleToFunctionParams<[number, string]> * // Expect: [] * type Example2 = TupleToFunctionParams<[]> * ``` */ export type TupleToFunctionParams = T /** * @description Get a function return type from a tuple (last element). * * @example * ``` * // Expect: string * type Example1 = TupleToFunctionReturn<[number, string]> * // Expect: never * type Example2 = TupleToFunctionReturn<[]> * ``` */ export type TupleToFunctionReturn = TupleLast /** * @description Convert a tuple to a union of single-element tuples. * * @example * ``` * // Expect: [1] | [2] * type Example1 = TupleToUnionOfTuples<[1, 2]> * // Expect: never * type Example2 = TupleToUnionOfTuples<[]> * ``` */ export type TupleToUnionOfTuples = { [K in keyof T]: [T[K]] }[number] /** * @description Convert a tuple to a readonly tuple. * * @example * ``` * // Expect: readonly [1, 2] * type Example1 = TupleToReadonly<[1, 2]> * // Expect: readonly [] * type Example2 = TupleToReadonly<[]> * ``` */ export type TupleToReadonly = Readonly /** * @description Convert a tuple to a mutable tuple. * * @example * ``` * // Expect: [1, 2] * type Example1 = TupleToMutable * // Expect: [] * type Example2 = TupleToMutable * ``` */ export type TupleToMutable = { -readonly [K in keyof T]: T[K] }