import type {Sum} from './sum'; import type {LessThanOrEqual} from './less-than-or-equal'; import type {GreaterThanOrEqual} from './greater-than-or-equal'; import type {GreaterThan} from './greater-than'; import type {IsNegative} from './numeric'; import type {Not, TupleMin} from './internal'; import type {IsEqual} from './is-equal'; import type {And} from './and'; import type {ArraySplice} from './array-splice'; /** Returns an array slice of a given range, just like `Array#slice()`. @example ``` import type {ArraySlice} from 'type-fest'; type T0 = ArraySlice<[0, 1, 2, 3, 4]>; //=> [0, 1, 2, 3, 4] type T1 = ArraySlice<[0, 1, 2, 3, 4], 0, -1>; //=> [0, 1, 2, 3] type T2 = ArraySlice<[0, 1, 2, 3, 4], 1, -2>; //=> [1, 2] type T3 = ArraySlice<[0, 1, 2, 3, 4], -2, 4>; //=> [3] type T4 = ArraySlice<[0, 1, 2, 3, 4], -2, -1>; //=> [3] type T5 = ArraySlice<[0, 1, 2, 3, 4], 0, -999>; //=> [] function arraySlice< const Array_ extends readonly unknown[], Start extends number = 0, End extends number = Array_['length'], >(array: Array_, start?: Start, end?: End) { return array.slice(start, end) as ArraySlice; } const slice = arraySlice([1, '2', {a: 3}, [4, 5]], 0, -1); typeof slice; //=> [1, '2', { readonly a: 3; }] slice[2].a; //=> 3 // @ts-expect-error -- TS2493: Tuple type '[1, "2", {readonly a: 3}]' of length '3' has no element at index '3'. slice[3]; ``` @category Array */ export type ArraySlice< Array_ extends readonly unknown[], Start extends number = never, End extends number = never, > = And, IsEqual> extends true ? Array_ : number extends Array_['length'] ? VariableLengthArraySliceHelper : ArraySliceHelper extends true ? 0 : Start, IsEqual extends true ? Array_['length'] : End>; type VariableLengthArraySliceHelper< Array_ extends readonly unknown[], Start extends number, End extends number, > = And>, IsEqual> extends true ? ArraySplice : And< And>, Not>>, IsEqual, true> > extends true ? ArraySliceByPositiveIndex : []; type ArraySliceHelper< Array_ extends readonly unknown[], Start extends number = 0, End extends number = Array_['length'], TraversedElement extends Array = [], Result extends Array = [], ArrayLength extends number = Array_['length'], PositiveS extends number = IsNegative extends true ? Sum extends infer AddResult extends number ? number extends AddResult // (ArrayLength + Start) < 0 ? 0 : AddResult : never : Start, PositiveE extends number = IsNegative extends true ? Sum : End, > = true extends [IsNegative, LessThanOrEqual, GreaterThanOrEqual][number] ? [] : ArraySliceByPositiveIndex, TupleMin<[PositiveE, ArrayLength]>>; type ArraySliceByPositiveIndex< Array_ extends readonly unknown[], Start extends number, End extends number, Result extends Array = [], > = Start extends End ? Result : ArraySliceByPositiveIndex, End, [...Result, Array_[Start]]>;