类型体操入门:Slice

Extreme 难度的 Slice 过关了,终于可以自称类型体操入门了(喜)

题面

type-challenges/questions/00216-extreme-slice/README.md at main · type-challenges/type-challenges

Slice extreme array

by Anthony Fu @antfu

Take the Challgene

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]

Back Share your Solutions Check out Solutions

思路

看上去很简单?这真的是 Extreme 难度吗?
难度主要在数字的转换上。TypeScript不支持直接做类型的加减法,所以需要体操一下获得 Add1<N>MinusXY<X, Y>

type Push1<X extends any[]> = [...X, 1];
type ArrFrom<N, A extends any[] = []> = A["length"] extends N ? A : ArrFrom<N, Push1<A>>;
type Add1<N> = [...ArrFrom<N>, 1]["length"];
type Minus1<N> = ArrFrom<N> extends [infer _1, ...infer Rest] ? Rest["length"] : never;
type MinusXY<X, Y> = Y extends 0 ? X : MinusXY<Minus1<X>, Minus1<Y>>;
type Abs<X extends number> = `${X}` extends `-${infer R extends number}` ? R : X;
type IsNeg<X extends number> = Abs<X> extends X ? false : true

剩下的就很简单了

type RemoveFirstN<N, Arr extends any[], Removed = 0> = N extends Removed 
  ? Arr
  : Arr extends [infer _1, ...infer Rest extends any[]]
    ? RemoveFirstN<N, Rest, Add1<Removed>>
    : [];
type KeepFirstN<N, Arr extends any[], Ret extends any[] = [], Kept = 0> = Kept extends N
  ? Ret
  : Arr extends [infer _1, ...infer Rest extends any[]]
    ? KeepFirstN<N, Rest, [...Ret, _1], Add1<Kept>>
    : [];
type SliceNoNeg<Arr extends any[], From, To> = 
  RemoveFirstN<From, Arr> extends infer Res extends any[]
    ? KeepFirstN<To, Res, [], From>
    : never;
type ConvertToPositive<N, X extends number> = IsNeg<X> extends true
  ? MinusXY<N, Abs<X>>
  : X;
type Slice<Arr extends any[], From extends number = 0, To extends number = Arr['length']> = 
  SliceNoNeg<Arr, ConvertToPositive<Arr['length'], From>, ConvertToPositive<Arr['length'], To>>

所以

这类型体操纯属在折磨自己了吧

Previous  Next

Loading...