Slice

Challenge

Implement the JavaScript Array.slice function in the type system. Slice<Arr, Start, End> takes the three argument. The output should be a subarray of Arr from index Start to End. Indexes with negative numbers should be counted from reversely.

For example

type Arr = [1, 2, 3, 4, 5];
type Result = Slice<Arr, 2, 4>; // expected to be [3, 4]

Solution

type NormalizeIndex< T extends unknown[], I extends number, P extends unknown[] = []

= ${I} extends -${infer N} ? ${P['length']} extends N

? T['length']
: T extends [...infer A, infer B]
? NormalizeIndex<A, I, [...P, B]>
: T['length']

: I

type GG = NormalizeIndex<[2,3], -1>

type Slice< Arr extends number[], Start extends number = 0, End extends number = Arr[‘length’], NStart extends number = NormalizeIndex<Arr, Start>, NEnd extends number = NormalizeIndex<Arr, End>, I extends unknown[] = []

= I[‘length’] extends NEnd | Arr[‘length’] ? [] : I[‘length’] extends NStart ? […I, unknown][‘length’] extends number

? [
    Arr[I['length']],
    ...Slice<
      Arr,
      Start,
      End,
      [...I, unknown]['length'],
      NEnd,
      [...I, unknown]
    >
  ]
: never

: Slice<Arr, Start, End, NStart, NEnd, […I, unknown]>

References