/** Get the first element */ export type TupleHead = T[0]; /** Remove the first element */ export type TupleTail = T extends [] ? [] : T extends [unknown] ? [] : T extends [unknown, ...infer U] ? U : unknown[]; export type TupleShift = TupleTail; /** Get the last element */ export type TupleLast = T[TupleTail['length']]; /** Remove the last element */ export type TupleRemoveLast = TypeAssert, T>, any[]>; /** Insert element at first */ export type TupleUnshift = [X, ...T]; /** Append element at last */ export type TuplePush = [...T, X]; /** Concat two tuples */ export type TupleConcat = [...A, ...B]; export type TypeAssert = T extends A ? T : never; export type Overwrite = { [P in keyof T]: S[P]; }; /** * Whether literal type is in Tuple contains literal, * * @example ```ts * type Foo = isInType<['ab', 'cd'], 'ab'> * ``` * @returns boolean */ export type isInLiteralTuple = [Extract] extends [never] ? false : true; export type TupleToUnion = T[number]; export type Reverse = Reverse_; type Reverse_ = { 1: Result; 0: Reverse_, TupleUnshift>>; }[Tuple extends [] ? 1 : 0]; export type FlattenNestedTuple = { [K in keyof T]: FlattenTuple; }; /** * Convert const type to type const input = [1, 2] as const * @example ```ts * const input = [1, [2, 3]] as const // note the `as const` * type Result = FlattenTuple // [1, 2 | 3] * ``` * */ type FlattenTuple = T extends readonly (infer U)[] ? U extends ((any)[]) ? TupleToUnion : U : T; export {};