[Typescript] 139. Extreme - Slice

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]

 

/* _____________ Your Code Here _____________ */

type SliceLeft<Arr extends readonly any[], Start, isNegStart, PrevArr extends readonly any[] = []> = 
  (isNegStart extends true ? Arr['length'] : PrevArr['length']) extends Start ? Arr
  : Arr extends [infer TFirst, ...infer TRest] ? SliceLeft<TRest, Start, isNegStart, [...PrevArr, TFirst]>
  : [];
type SliceLeftIgnoreSign<Arr extends readonly any[], Start extends number> = 
  `${Start}` extends `-${infer PosStart extends number}` ? SliceLeft<Arr, PosStart, true> : SliceLeft<Arr, Start, false>;


type SliceRight<Arr extends readonly any[], End extends number, isNegEnd, PrevArr extends readonly any[] = []> = 
  (isNegEnd extends true ? PrevArr['length'] : Arr['length']) extends End ? Arr
  : Arr extends [...infer TRest, infer TLast] ? SliceRight<TRest, End, isNegEnd, [TLast, ...PrevArr]>
  : [];
type SliceRightIgnoreSign<Arr extends readonly any[], End extends number> = 
  `${End}` extends `-${infer PosEnd extends number}` ? SliceRight<Arr, PosEnd, true> : SliceRight<Arr, End, false>;


type Slice<Arr extends readonly any[], Start extends number = 0, End extends number = Arr['length']> = 
  `${Start}` extends `-${string}` ? SliceRightIgnoreSign<SliceLeftIgnoreSign<Arr, Start>, End>
  : SliceLeftIgnoreSign<SliceRightIgnoreSign<Arr, End>, Start>


/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'

type Arr = [1, 2, 3, 4, 5]

type cases = [
  // basic
  Expect<Equal<Slice<Arr, 0, 1>, [1]>>,
  Expect<Equal<Slice<Arr, 0, 0>, []>>,
  Expect<Equal<Slice<Arr, 2, 4>, [3, 4]>>,

  // optional args
  Expect<Equal<Slice<[]>, []>>,
  Expect<Equal<Slice<Arr>, Arr>>,
  Expect<Equal<Slice<Arr, 0>, Arr>>,
  Expect<Equal<Slice<Arr, 2>, [3, 4, 5]>>,

  // negative index
  Expect<Equal<Slice<Arr, 0, -1>, [1, 2, 3, 4]>>,
  Expect<Equal<Slice<Arr, -3, -1>, [3, 4]>>,

  // invalid
  Expect<Equal<Slice<Arr, 10>, []>>,
  Expect<Equal<Slice<Arr, 1, 0>, []>>,
  Expect<Equal<Slice<Arr, 10, 20>, []>>,
]

 

posted @ 2022-12-16 15:28  Zhentiw  阅读(13)  评论(0编辑  收藏  举报