-
-
Notifications
You must be signed in to change notification settings - Fork 679
Expand file tree
/
Copy patharray-slice.d.ts
More file actions
132 lines (113 loc) · 4.22 KB
/
array-slice.d.ts
File metadata and controls
132 lines (113 loc) · 4.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import type {Sum} from './sum.d.ts';
import type {LessThanOrEqual} from './less-than-or-equal.d.ts';
import type {GreaterThanOrEqual} from './greater-than-or-equal.d.ts';
import type {GreaterThan} from './greater-than.d.ts';
import type {IsNegative} from './numeric.d.ts';
import type {Not, TupleMin} from './internal/index.d.ts';
import type {IsEqual} from './is-equal.d.ts';
import type {And} from './and.d.ts';
import type {ArraySplice} from './array-splice.d.ts';
import type {IsNever} from './is-never.d.ts';
/**
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<Array_, Start, End>;
}
const slice = arraySlice([1, '2', {a: 3}, [4, 5]], 0, -1);
type Slice = typeof slice;
//=> [1, '2', {readonly a: 3}]
const value = slice[2].a;
//=> 3
// @ts-expect-error -- TS2493: Tuple type '[1, "2", {readonly a: 3}]' of length '3' has no element at index '3'.
const invalidIndexAccess = slice[3];
```
@category Array
*/
export type ArraySlice<
Array_ extends readonly unknown[],
Start extends number = never,
End extends number = never,
> = Array_ extends unknown // To distributive type
? IsNever<Start> extends true
? IsNever<End> extends true
? _ArraySlice<Array_, Start, End>
: End extends unknown // To distribute `End`
? _ArraySlice<Array_, Start, End>
: never // Never happens
: IsNever<End> extends true
? Start extends unknown // To distribute `Start`
? _ArraySlice<Array_, Start, End>
: never // Never happens
: Start extends unknown // To distribute `Start`
? End extends unknown // To distribute `End`
? _ArraySlice<Array_, Start, End>
: never // Never happens
: never // Never happens
: never; // Never happens
type _ArraySlice<
Array_ extends readonly unknown[],
Start extends number = 0,
End extends number = Array_['length'],
> = And<IsEqual<Start, never>, IsEqual<End, never>> extends true
? Array_
: number extends Array_['length']
? VariableLengthArraySliceHelper<Array_, Start, End>
: ArraySliceHelper<Array_, IsEqual<Start, never> extends true ? 0 : Start, IsEqual<End, never> extends true ? Array_['length'] : End>;
type VariableLengthArraySliceHelper<
Array_ extends readonly unknown[],
Start extends number,
End extends number,
> = And<Not<IsNegative<Start>>, IsEqual<End, never>> extends true
? ArraySplice<Array_, 0, Start>
: And<
And<Not<IsNegative<Start>>, Not<IsNegative<End>>>,
IsEqual<GreaterThan<End, Start>, true>
> extends true
? ArraySliceByPositiveIndex<Array_, Start, End>
: [];
type ArraySliceHelper<
Array_ extends readonly unknown[],
Start extends number = 0,
End extends number = Array_['length'],
TraversedElement extends Array<Array_[number]> = [],
Result extends Array<Array_[number]> = [],
ArrayLength extends number = Array_['length'],
PositiveS extends number = IsNegative<Start> extends true
? Sum<ArrayLength, Start> extends infer AddResult extends number
? number extends AddResult // (ArrayLength + Start) < 0
? 0
: GreaterThan<AddResult, 0> extends true ? AddResult : 0
: never
: Start,
PositiveE extends number = IsNegative<End> extends true ? Sum<ArrayLength, End> : End,
> = true extends [IsNegative<PositiveS>, LessThanOrEqual<PositiveE, PositiveS>, GreaterThanOrEqual<PositiveS, ArrayLength>][number]
? []
: ArraySliceByPositiveIndex<Array_, TupleMin<[PositiveS, ArrayLength]>, TupleMin<[PositiveE, ArrayLength]>>;
type ArraySliceByPositiveIndex<
Array_ extends readonly unknown[],
Start extends number,
End extends number,
Result extends Array<Array_[number]> = [],
> = Start extends End
? Result
: ArraySliceByPositiveIndex<Array_, Sum<Start, 1>, End, [...Result, Array_[Start]]>;
export {};