34286-hard-take-elements

Back

type Take<N extends number, Arr extends any[], _Result extends any[] = [], _AbsN = `${N}` extends `-${infer A extends number}` ? A : N> =
  _Result[`length`] extends _AbsN ? _Result :
  // Arr extends [] ? _Result :  //optional
  N extends _AbsN ?
  Arr extends [infer F, ...infer R] ? Take<N, R, [..._Result, F]> : _Result : //positive
  Arr extends [...infer R, infer L] ? Take<N, R, [L, ..._Result]> : _Result;  //nagative

Solution by E-uler #34715

type Take<N extends number, Arr extends unknown[], Result extends unknown[] = []> = 
    Absolute<N> extends 0 
        ? []
        : Or<[
            Absolute<N> extends Result["length"] ? true : false,
            Arr extends [] ? true : false
        ]> extends true
            ? Result
            : N extends Absolute<N>
                ? Arr extends [infer First, ...infer Rest]
                    ? Take<N, Rest, [...Result, First]>
                    : never
                : Arr extends [...infer Rest, infer Last]
                    ? Take<N, Rest, [Last, ...Result]>
                    : never;

type Absolute<N extends number> = `${N}` extends `-${infer AbsoluteN extends number}` ? AbsoluteN : N;

type NonEmptyArray<T> = [T, ...T[]];

type Or<T extends NonEmptyArray<boolean>> = T extends [infer First, ...infer Rest]
    ? true extends First
        ? true
        : Rest extends NonEmptyArray<boolean>
            ? Or<Rest>
            : false
    : never;

Solution by shobande-femi #34605

// reverse order of T
// eg.
// Reverse<[1, 2, 3]> -> [3, 2, 1]
// Reverse<[]> -> []
type Reverse<T extends unknown[]> = T extends [infer First, ...infer Rest] ? [...Reverse<Rest>, First] : [];

type Take<
  N extends number,
  Arr extends unknown[],
  Result extends unknown[] = []
> = `${N}` extends `-${infer A extends number}`
  ? Reverse<Take<A, Reverse<Arr>>>
  : Result["length"] extends N
  ? Result
  : Arr extends [infer First, ...infer Rest extends unknown[]]
  ? Take<N, Rest, [...Result, First]>
  : Result;

Solution by yukicountry #34436

type Take<N extends number, Arr extends unknown[]>
  = `${N}` extends `-${infer I extends number}` // Check for negative here once
    ? TupleTrim<[any], [], `${I}`, Arr>
  : TupleTrim<[], [any], `${N}`, Arr>

type TupleTrim<Head extends any[], Tail extends any[], Key extends string, Arr extends unknown[]>
  = Key extends keyof Arr
    ? Arr extends [...Head, ...infer Rest, ...Tail] ? TupleTrim<Head, Tail, Key, Rest> : never
  : Arr // i.e. '2' extends ['0', '1'] or '2' extends ['0']

Playground

Solution by teamchong #34407

type Take<N extends number, A> = `${N}` extends `-${infer M extends number}`
  ? Slice<M, A, 1>
  : Slice<N, A, 0>;

type Slice<N, A, L, R extends unknown[] = []> = N extends R['length']
  ? R
  : A extends (L extends 1 ? [...infer T, infer V] : [infer V, ...infer T])
    ? Slice<N, T, L, L extends 1 ? [V, ...R] : [...R, V]>
    : R;

Solution by alexandroppolus #34383

type MuseOne<T extends number | string, K extends unknown[] = []> = `${[...K, '']['length'] extends number
  ? [...K, '']['length']
  : ''}` extends `${T}`
  ? K['length']
  : MuseOne<T, [...K, '']>;

type Abs<T extends number> = `${T}` extends `-${infer K}` ? K : T;

type TakeFromFirst<T extends number, K extends unknown[]> = T extends 0
  ? []
  : K extends [infer L, ...infer R]
  ? [L, ...TakeFromFirst<MuseOne<T>, R>]
  : [];

type TakeFromLast<T extends number | string, K extends unknown[]> = T extends 0
  ? []
  : K extends [...infer L, infer R]
  ? [...TakeFromLast<MuseOne<T>, L>, R]
  : [];

type Take<T extends number, K extends unknown[]> = `${T}` extends `-${number}`
  ? TakeFromLast<Abs<T>, K>
  : TakeFromFirst<T, K>;

Solution by chhu1 #34354

type Take<N extends number, Arr extends unknown[]> = `${N}` extends `-${infer P extends number}`
  ? Reverse<_Take<P, Reverse<Arr>>>
  : _Take<N, Arr>

type _Take<N extends number, Arr extends unknown[], R extends unknown[] = []> = R['length'] extends N
  ? R
  : Arr extends [infer Head, ...infer Rest]
    ? _Take<N, Rest, [...R, Head]>
    : R

type Reverse<T extends unknown[]> = T extends [infer Head, ...infer Rest, infer Last]
  ? [Last, ...Reverse<Rest>, Head]
  : T

Solution by Sun79 #34351