ts-data-forge 1.5.2 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -44
- package/dist/array/array-utils.d.mts +661 -166
- package/dist/array/array-utils.d.mts.map +1 -1
- package/dist/array/array-utils.mjs +719 -79
- package/dist/array/array-utils.mjs.map +1 -1
- package/dist/array/index.d.mts +0 -1
- package/dist/array/index.d.mts.map +1 -1
- package/dist/array/index.mjs +0 -1
- package/dist/array/index.mjs.map +1 -1
- package/dist/collections/queue.mjs +0 -1
- package/dist/collections/queue.mjs.map +1 -1
- package/dist/collections/stack.mjs +4 -5
- package/dist/collections/stack.mjs.map +1 -1
- package/dist/functional/pipe.d.mts +56 -61
- package/dist/functional/pipe.d.mts.map +1 -1
- package/dist/functional/pipe.mjs.map +1 -1
- package/dist/globals.d.mts +10 -9
- package/dist/index.mjs +0 -1
- package/dist/index.mjs.map +1 -1
- package/dist/json/json.mjs +0 -1
- package/dist/json/json.mjs.map +1 -1
- package/dist/number/num.d.mts +1 -1
- package/package.json +2 -2
- package/src/array/array-utils-modification.test.mts +93 -67
- package/src/array/array-utils-overload-type-error.test.mts +2 -2
- package/src/array/array-utils-reducing-value.test.mts +31 -37
- package/src/array/array-utils-slice-clamped.test.mts +94 -70
- package/src/array/array-utils-transformation.test.mts +557 -10
- package/src/array/array-utils.mts +1457 -516
- package/src/array/index.mts +0 -1
- package/src/collections/queue.mts +2 -2
- package/src/collections/stack.mts +8 -8
- package/src/functional/pipe.mts +65 -75
- package/src/globals.d.mts +10 -9
- package/src/number/num.mts +1 -1
- package/dist/array/tuple-utils.d.mts +0 -407
- package/dist/array/tuple-utils.d.mts.map +0 -1
- package/dist/array/tuple-utils.mjs +0 -345
- package/dist/array/tuple-utils.mjs.map +0 -1
- package/src/array/tuple-utils.mts +0 -498
- package/src/array/tuple-utils.test.mts +0 -518
|
@@ -15,6 +15,17 @@ import { castMutable, tp, unknownToString } from '../others/index.mjs';
|
|
|
15
15
|
* ensuring immutability.
|
|
16
16
|
*/
|
|
17
17
|
export namespace Arr {
|
|
18
|
+
type ArrayIndex<Ar extends readonly unknown[]> =
|
|
19
|
+
IsFixedLengthList<Ar> extends true ? IndexOfTuple<Ar> : SizeType.Arr;
|
|
20
|
+
|
|
21
|
+
type ArgArrayIndex<Ar extends readonly unknown[]> =
|
|
22
|
+
IsFixedLengthList<Ar> extends true ? IndexOfTuple<Ar> : SizeType.ArgArr;
|
|
23
|
+
|
|
24
|
+
type ArgArrayIndexWithNegative<Ar extends readonly unknown[]> =
|
|
25
|
+
IsFixedLengthList<Ar> extends true
|
|
26
|
+
? IndexOfTuple<[...Ar, 0]> | NegativeIndexOfTuple<Ar>
|
|
27
|
+
: SizeType.ArgArrWithNegative;
|
|
28
|
+
|
|
18
29
|
/**
|
|
19
30
|
* Returns the size (length) of an array as a type-safe branded integer.
|
|
20
31
|
*
|
|
@@ -40,7 +51,7 @@ export namespace Arr {
|
|
|
40
51
|
* // Type: IntersectBrand<PositiveNumber, SizeType.Arr>
|
|
41
52
|
* // Value: 3 (branded, guaranteed positive)
|
|
42
53
|
*
|
|
43
|
-
* const nonEmpty: NonEmptyArray<string> = ['a', 'b']
|
|
54
|
+
* const nonEmpty: NonEmptyArray<string> = ['a', 'b'];
|
|
44
55
|
* const nonEmptySize = Arr.size(nonEmpty);
|
|
45
56
|
* // Type: IntersectBrand<PositiveNumber, SizeType.Arr>
|
|
46
57
|
* // Guaranteed to be > 0
|
|
@@ -70,13 +81,6 @@ export namespace Arr {
|
|
|
70
81
|
* const indices = Arr.seq(dataSize); // Creates [0, 1, 2]
|
|
71
82
|
* const zeros = Arr.zeros(dataSize); // Creates [0, 0, 0]
|
|
72
83
|
*
|
|
73
|
-
* // Safe for bounds checking
|
|
74
|
-
* const isValidIndex = (index: number) => index >= 0 && index < dataSize;
|
|
75
|
-
*
|
|
76
|
-
* // Comparison with other sizes
|
|
77
|
-
* const otherArray = ['a', 'b'];
|
|
78
|
-
* const sizeDiff = Uint32.sub(Arr.size(data), Arr.size(otherArray)); // 1
|
|
79
|
-
*
|
|
80
84
|
* // Functional composition
|
|
81
85
|
* const arrays = [
|
|
82
86
|
* [1, 2],
|
|
@@ -103,17 +107,13 @@ export namespace Arr {
|
|
|
103
107
|
* @see {@link isEmpty} for checking if size is 0
|
|
104
108
|
* @see {@link isNonEmpty} for checking if size > 0
|
|
105
109
|
*/
|
|
106
|
-
export
|
|
110
|
+
export const size = <Ar extends readonly unknown[]>(
|
|
107
111
|
array: Ar,
|
|
108
|
-
):
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return asUint32(array.length);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export const length = size;
|
|
112
|
+
): Ar extends NonEmptyArray<unknown>
|
|
113
|
+
? IntersectBrand<PositiveNumber, SizeType.Arr>
|
|
114
|
+
: SizeType.Arr =>
|
|
115
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
116
|
+
array.length as never;
|
|
117
117
|
|
|
118
118
|
// type guard
|
|
119
119
|
|
|
@@ -179,26 +179,11 @@ export namespace Arr {
|
|
|
179
179
|
* if (Arr.isEmpty(arr)) {
|
|
180
180
|
* // arr is now typed as readonly []
|
|
181
181
|
* console.log('Array is empty');
|
|
182
|
+
* // arr[0]; // type error!
|
|
182
183
|
* return 0;
|
|
183
|
-
* } else {
|
|
184
|
-
* // arr is now typed as NonEmptyArray<number>
|
|
185
|
-
* return arr[0]; // Safe access - TypeScript knows it's non-empty
|
|
186
184
|
* }
|
|
187
185
|
* }
|
|
188
186
|
*
|
|
189
|
-
* // Conditional processing
|
|
190
|
-
* const data = [10, 20, 30];
|
|
191
|
-
* if (!Arr.isEmpty(data)) {
|
|
192
|
-
* // Safe to access elements
|
|
193
|
-
* const firstElement = data[0]; // No undefined risk
|
|
194
|
-
* const lastElement = data[data.length - 1];
|
|
195
|
-
* }
|
|
196
|
-
*
|
|
197
|
-
* // Filtering empty arrays
|
|
198
|
-
* const arrayList: readonly number[][] = [[1, 2], [], [3], []];
|
|
199
|
-
* const nonEmptyArrays = arrayList.filter(arr => !Arr.isEmpty(arr));
|
|
200
|
-
* // nonEmptyArrays: [[1, 2], [3]]
|
|
201
|
-
*
|
|
202
187
|
* // Early returns
|
|
203
188
|
* function sumArray(numbers: readonly number[]): number {
|
|
204
189
|
* if (Arr.isEmpty(numbers)) {
|
|
@@ -207,12 +192,6 @@ export namespace Arr {
|
|
|
207
192
|
* return numbers.reduce((sum, n) => sum + n, 0);
|
|
208
193
|
* }
|
|
209
194
|
*
|
|
210
|
-
* // Type inference examples
|
|
211
|
-
* const testEmpty = [] as const;
|
|
212
|
-
* const testNonEmpty = [1, 2] as const;
|
|
213
|
-
*
|
|
214
|
-
* expectType<Parameters<typeof Arr.isEmpty>[0], readonly unknown[]>('=');
|
|
215
|
-
* expectType<ReturnType<typeof Arr.isEmpty>, boolean>('=');
|
|
216
195
|
* ```
|
|
217
196
|
*
|
|
218
197
|
* @see {@link isNonEmpty} for the opposite check (non-empty arrays)
|
|
@@ -255,16 +234,14 @@ export namespace Arr {
|
|
|
255
234
|
*
|
|
256
235
|
* // Safe operations on non-empty arrays
|
|
257
236
|
* function processData(data: readonly string[]) {
|
|
258
|
-
* if (Arr.isNonEmpty(data))
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
* const reduced = data.reduce((acc, item) => acc + item.length, 0);
|
|
267
|
-
* }
|
|
237
|
+
* if (!Arr.isNonEmpty(data)) return; // early return pattern
|
|
238
|
+
*
|
|
239
|
+
* // This is now safe without undefined checks
|
|
240
|
+
* const first = data[0];
|
|
241
|
+
*
|
|
242
|
+
* // Can safely use non-empty array methods
|
|
243
|
+
* const lastElement = Arr.last(data);
|
|
244
|
+
*
|
|
268
245
|
* }
|
|
269
246
|
*
|
|
270
247
|
* // Filtering and working with arrays
|
|
@@ -289,7 +266,7 @@ export namespace Arr {
|
|
|
289
266
|
* }
|
|
290
267
|
*
|
|
291
268
|
* // numbers is now NonEmptyArray<number>
|
|
292
|
-
* return
|
|
269
|
+
* return Arr.sum(numbers) / Arr.size(numbers);
|
|
293
270
|
* }
|
|
294
271
|
*
|
|
295
272
|
* // Functional composition
|
|
@@ -353,7 +330,7 @@ export namespace Arr {
|
|
|
353
330
|
* Arr.isArrayOfLength([1, 2], 3); // false
|
|
354
331
|
* ```
|
|
355
332
|
*/
|
|
356
|
-
export const isArrayOfLength = <E, N extends SizeType.
|
|
333
|
+
export const isArrayOfLength = <E, N extends SizeType.ArgArr>(
|
|
357
334
|
array: readonly E[],
|
|
358
335
|
len: N,
|
|
359
336
|
): array is ArrayOfLength<N, E> => array.length === len;
|
|
@@ -374,7 +351,7 @@ export namespace Arr {
|
|
|
374
351
|
* Arr.isArrayAtLeastLength([1], 2); // false
|
|
375
352
|
* ```
|
|
376
353
|
*/
|
|
377
|
-
export const isArrayAtLeastLength = <E, N extends SizeType.
|
|
354
|
+
export const isArrayAtLeastLength = <E, N extends SizeType.ArgArr>(
|
|
378
355
|
array: readonly E[],
|
|
379
356
|
len: N,
|
|
380
357
|
): array is ArrayAtLeastLen<N, E> => array.length >= len;
|
|
@@ -396,7 +373,7 @@ export namespace Arr {
|
|
|
396
373
|
*/
|
|
397
374
|
export const indexIsInRange = <E,>(
|
|
398
375
|
array: readonly E[],
|
|
399
|
-
index: SizeType.
|
|
376
|
+
index: SizeType.ArgArr,
|
|
400
377
|
): boolean => Num.isInRange(0, array.length)(index);
|
|
401
378
|
|
|
402
379
|
// array creation
|
|
@@ -437,24 +414,15 @@ export namespace Arr {
|
|
|
437
414
|
* expectType<typeof maybeEmpty, readonly 0[]>('=');
|
|
438
415
|
* ```
|
|
439
416
|
*/
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
/**
|
|
451
|
-
* Create array of zeros.
|
|
452
|
-
*/
|
|
453
|
-
export function zeros(len: SizeType.ArgArrNonNegative): readonly 0[];
|
|
454
|
-
|
|
455
|
-
export function zeros(len: SizeType.ArgArrNonNegative): readonly 0[] {
|
|
456
|
-
return Array.from<0>({ length: len }).fill(0);
|
|
457
|
-
}
|
|
417
|
+
export const zeros = <N extends SizeType.ArgArr>(
|
|
418
|
+
len: N,
|
|
419
|
+
): N extends SmallUint
|
|
420
|
+
? ArrayOfLength<N, 0>
|
|
421
|
+
: N extends SizeType.ArgArrPositive
|
|
422
|
+
? NonEmptyArray<0>
|
|
423
|
+
: readonly 0[] =>
|
|
424
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
425
|
+
Array.from<0>({ length: len }).fill(0) as never;
|
|
458
426
|
|
|
459
427
|
/**
|
|
460
428
|
* Creates a sequence of consecutive integers from 0 to `len-1`.
|
|
@@ -497,19 +465,15 @@ export namespace Arr {
|
|
|
497
465
|
* expectType<typeof single, readonly [0]>('=');
|
|
498
466
|
* ```
|
|
499
467
|
*/
|
|
500
|
-
export
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
len: SizeType.ArgArrNonNegative,
|
|
510
|
-
): readonly SizeType.Arr[] {
|
|
511
|
-
return Array.from({ length: len }, (_, i) => asUint32(i));
|
|
512
|
-
}
|
|
468
|
+
export const seq = <N extends SizeType.ArgArr>(
|
|
469
|
+
len: N,
|
|
470
|
+
): N extends SmallUint
|
|
471
|
+
? Seq<N>
|
|
472
|
+
: N extends SizeType.ArgArrPositive
|
|
473
|
+
? NonEmptyArray<SizeType.Arr>
|
|
474
|
+
: readonly SizeType.Arr[] =>
|
|
475
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
476
|
+
Array.from({ length: len }, (_, i) => i) as never;
|
|
513
477
|
|
|
514
478
|
/**
|
|
515
479
|
* Creates a new array of the specified length, with each position filled with the provided initial value.
|
|
@@ -559,29 +523,16 @@ export namespace Arr {
|
|
|
559
523
|
* @see {@link zeros} for creating arrays filled with zeros
|
|
560
524
|
* @see {@link seq} for creating sequences of consecutive integers
|
|
561
525
|
*/
|
|
562
|
-
export
|
|
526
|
+
export const create = <const V, N extends SizeType.ArgArr>(
|
|
563
527
|
len: N,
|
|
564
528
|
init: V,
|
|
565
|
-
):
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
export function create<const V>(
|
|
573
|
-
len: SizeType.ArgArrNonNegative,
|
|
574
|
-
init: V,
|
|
575
|
-
): readonly V[];
|
|
576
|
-
|
|
577
|
-
export function create<const V>(
|
|
578
|
-
len: SizeType.ArgArrNonNegative,
|
|
579
|
-
init: V,
|
|
580
|
-
): readonly V[] {
|
|
581
|
-
return Array.from({ length: Math.max(0, len) }, () => init);
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
export const newArray = create;
|
|
529
|
+
): N extends SmallUint
|
|
530
|
+
? ArrayOfLength<N, V>
|
|
531
|
+
: N extends SizeType.ArgArrPositive
|
|
532
|
+
? NonEmptyArray<V>
|
|
533
|
+
: readonly V[] =>
|
|
534
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
535
|
+
Array.from({ length: Math.max(0, len) }, () => init) as never;
|
|
585
536
|
|
|
586
537
|
/**
|
|
587
538
|
* Creates an array from a generator function.
|
|
@@ -787,7 +738,10 @@ export namespace Arr {
|
|
|
787
738
|
*
|
|
788
739
|
* // Functional programming patterns
|
|
789
740
|
* const squares = Arr.range(1, 6).map(x => x * x); // [1, 4, 9, 16, 25]
|
|
790
|
-
* const fibonacci = Arr.range(0, 10).reduce((acc, _, i) => {
|
|
741
|
+
* const fibonacci = Arr.range(0, 10).reduce((acc, _, i) => {
|
|
742
|
+
* if (i <= 1) return [...acc, i];
|
|
743
|
+
* return [...acc, acc[i-1] + acc[i-2]];
|
|
744
|
+
* }, [] as number[]); // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
|
|
791
745
|
*
|
|
792
746
|
* // Type inference examples showing precise vs general types
|
|
793
747
|
* expectType<typeof range1to4, readonly [1, 2, 3, 4]>('='); // Precise tuple
|
|
@@ -942,21 +896,21 @@ export namespace Arr {
|
|
|
942
896
|
* @see {@link Optional.unwrapOr} for safe unwrapping with defaults
|
|
943
897
|
* @see {@link Optional.map} for transforming Optional values
|
|
944
898
|
*/
|
|
945
|
-
export function at<
|
|
946
|
-
array:
|
|
947
|
-
index:
|
|
948
|
-
): Optional<
|
|
899
|
+
export function at<Ar extends readonly unknown[]>(
|
|
900
|
+
array: Ar,
|
|
901
|
+
index: ArgArrayIndexWithNegative<Ar>,
|
|
902
|
+
): Optional<Ar[number]>;
|
|
949
903
|
|
|
950
904
|
// Curried version
|
|
951
905
|
|
|
952
906
|
export function at(
|
|
953
|
-
index: SizeType.
|
|
907
|
+
index: SizeType.ArgArrWithNegative,
|
|
954
908
|
): <E>(array: readonly E[]) => Optional<E>;
|
|
955
909
|
|
|
956
910
|
export function at<E>(
|
|
957
911
|
...args:
|
|
958
|
-
| readonly [array: readonly E[], index: SizeType.
|
|
959
|
-
| readonly [index: SizeType.
|
|
912
|
+
| readonly [array: readonly E[], index: SizeType.ArgArrWithNegative]
|
|
913
|
+
| readonly [index: SizeType.ArgArrWithNegative]
|
|
960
914
|
): Optional<E> | ((array: readonly E[]) => Optional<E>) {
|
|
961
915
|
switch (args.length) {
|
|
962
916
|
case 2: {
|
|
@@ -971,7 +925,7 @@ export namespace Arr {
|
|
|
971
925
|
}
|
|
972
926
|
case 1: {
|
|
973
927
|
const [index] = args;
|
|
974
|
-
return (array
|
|
928
|
+
return (array) => at(array, index);
|
|
975
929
|
}
|
|
976
930
|
}
|
|
977
931
|
}
|
|
@@ -1047,20 +1001,17 @@ export namespace Arr {
|
|
|
1047
1001
|
* @see {@link at} for accessing elements at specific indices
|
|
1048
1002
|
* @see {@link tail} for getting all elements except the first
|
|
1049
1003
|
*/
|
|
1050
|
-
export
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
const element = array.at(0);
|
|
1062
|
-
return element === undefined ? Optional.none : Optional.some(element);
|
|
1063
|
-
}
|
|
1004
|
+
export const head = <Ar extends readonly unknown[]>(
|
|
1005
|
+
array: Ar,
|
|
1006
|
+
): Ar extends readonly []
|
|
1007
|
+
? Optional.None
|
|
1008
|
+
: Ar extends readonly [infer E, ...unknown[]]
|
|
1009
|
+
? Optional.Some<E>
|
|
1010
|
+
: Ar extends NonEmptyArray<infer E>
|
|
1011
|
+
? Optional.Some<E>
|
|
1012
|
+
: Optional<Ar[number]> =>
|
|
1013
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
1014
|
+
(array.length === 0 ? Optional.none : Optional.some(array.at(0))) as never;
|
|
1064
1015
|
|
|
1065
1016
|
/**
|
|
1066
1017
|
* Returns the last element of an array wrapped in an Optional.
|
|
@@ -1142,20 +1093,17 @@ export namespace Arr {
|
|
|
1142
1093
|
* @see {@link at} for accessing elements at specific indices with negative indexing support
|
|
1143
1094
|
* @see {@link butLast} for getting all elements except the last
|
|
1144
1095
|
*/
|
|
1145
|
-
export
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
const element = array.at(-1);
|
|
1157
|
-
return element === undefined ? Optional.none : Optional.some(element);
|
|
1158
|
-
}
|
|
1096
|
+
export const last = <Ar extends readonly unknown[]>(
|
|
1097
|
+
array: Ar,
|
|
1098
|
+
): Ar extends readonly []
|
|
1099
|
+
? Optional.None
|
|
1100
|
+
: Ar extends readonly [...unknown[], infer E]
|
|
1101
|
+
? Optional.Some<E>
|
|
1102
|
+
: Ar extends NonEmptyArray<infer E>
|
|
1103
|
+
? Optional.Some<E>
|
|
1104
|
+
: Optional<Ar[number]> =>
|
|
1105
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
1106
|
+
(array.length === 0 ? Optional.none : Optional.some(array.at(-1))) as never;
|
|
1159
1107
|
|
|
1160
1108
|
// slicing
|
|
1161
1109
|
|
|
@@ -1242,21 +1190,25 @@ export namespace Arr {
|
|
|
1242
1190
|
* @see {@link skip} for skipping the first N elements
|
|
1243
1191
|
* @see {@link takeLast} for taking the last N elements
|
|
1244
1192
|
*/
|
|
1245
|
-
export function sliceClamped<
|
|
1246
|
-
array:
|
|
1247
|
-
start:
|
|
1248
|
-
end:
|
|
1249
|
-
): readonly
|
|
1193
|
+
export function sliceClamped<Ar extends readonly unknown[]>(
|
|
1194
|
+
array: Ar,
|
|
1195
|
+
start: ArgArrayIndexWithNegative<Ar>,
|
|
1196
|
+
end: ArgArrayIndexWithNegative<Ar>,
|
|
1197
|
+
): readonly Ar[number][];
|
|
1250
1198
|
|
|
1251
1199
|
export function sliceClamped(
|
|
1252
|
-
start: SizeType.
|
|
1253
|
-
end: SizeType.
|
|
1200
|
+
start: SizeType.ArgArrWithNegative,
|
|
1201
|
+
end: SizeType.ArgArrWithNegative,
|
|
1254
1202
|
): <E>(array: readonly E[]) => readonly E[];
|
|
1255
1203
|
|
|
1256
1204
|
export function sliceClamped<E>(
|
|
1257
1205
|
...args:
|
|
1258
|
-
| readonly [
|
|
1259
|
-
|
|
1206
|
+
| readonly [
|
|
1207
|
+
readonly E[],
|
|
1208
|
+
SizeType.ArgArrWithNegative,
|
|
1209
|
+
SizeType.ArgArrWithNegative,
|
|
1210
|
+
]
|
|
1211
|
+
| readonly [SizeType.ArgArrWithNegative, SizeType.ArgArrWithNegative]
|
|
1260
1212
|
): readonly E[] | ((array: readonly E[]) => readonly E[]) {
|
|
1261
1213
|
switch (args.length) {
|
|
1262
1214
|
case 3: {
|
|
@@ -1332,41 +1284,37 @@ export namespace Arr {
|
|
|
1332
1284
|
* console.log(result); // [1, 2, 3]
|
|
1333
1285
|
* ```
|
|
1334
1286
|
*/
|
|
1335
|
-
export function take<
|
|
1287
|
+
export function take<
|
|
1288
|
+
Ar extends readonly unknown[],
|
|
1289
|
+
N extends SizeType.ArgArr,
|
|
1290
|
+
>(
|
|
1336
1291
|
array: Ar,
|
|
1337
1292
|
num: N,
|
|
1338
|
-
):
|
|
1339
|
-
|
|
1340
|
-
|
|
1293
|
+
): N extends SmallUint
|
|
1294
|
+
? List.Take<N, Ar>
|
|
1295
|
+
: N extends SizeType.ArgArrPositive
|
|
1296
|
+
? Ar extends NonEmptyArray<unknown>
|
|
1297
|
+
? NonEmptyArray<Ar[number]>
|
|
1298
|
+
: readonly Ar[number][]
|
|
1299
|
+
: readonly Ar[number][];
|
|
1300
|
+
|
|
1301
|
+
export function take<N extends SizeType.ArgArr>(
|
|
1341
1302
|
num: N,
|
|
1342
|
-
): <Ar extends readonly unknown[]>(
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
): <E>(array: NonEmptyArray<E>) => NonEmptyArray<E>;
|
|
1352
|
-
|
|
1353
|
-
export function take<E>(
|
|
1354
|
-
array: readonly E[],
|
|
1355
|
-
num: SizeType.ArgArrNonNegative,
|
|
1356
|
-
): readonly E[];
|
|
1357
|
-
|
|
1358
|
-
export function take(
|
|
1359
|
-
num: SizeType.ArgArrNonNegative,
|
|
1360
|
-
): <E>(array: readonly E[]) => readonly E[];
|
|
1303
|
+
): <Ar extends readonly unknown[]>(
|
|
1304
|
+
array: Ar,
|
|
1305
|
+
) => N extends SmallUint
|
|
1306
|
+
? List.Take<N, Ar>
|
|
1307
|
+
: N extends SizeType.ArgArrPositive
|
|
1308
|
+
? Ar extends NonEmptyArray<unknown>
|
|
1309
|
+
? NonEmptyArray<Ar[number]>
|
|
1310
|
+
: readonly Ar[number][]
|
|
1311
|
+
: readonly Ar[number][];
|
|
1361
1312
|
|
|
1362
1313
|
export function take<E>(
|
|
1363
1314
|
...args:
|
|
1364
|
-
| readonly [array: readonly E[], num: SizeType.
|
|
1365
|
-
| readonly [num: SizeType.
|
|
1366
|
-
):
|
|
1367
|
-
| readonly E[]
|
|
1368
|
-
| ((array: NonEmptyArray<E>) => NonEmptyArray<E>)
|
|
1369
|
-
| ((array: readonly E[]) => readonly E[]) {
|
|
1315
|
+
| readonly [array: readonly E[], num: SizeType.ArgArr]
|
|
1316
|
+
| readonly [num: SizeType.ArgArr]
|
|
1317
|
+
): readonly E[] | ((array: readonly E[]) => readonly E[]) {
|
|
1370
1318
|
switch (args.length) {
|
|
1371
1319
|
case 2: {
|
|
1372
1320
|
const [array, num] = args;
|
|
@@ -1374,7 +1322,7 @@ export namespace Arr {
|
|
|
1374
1322
|
}
|
|
1375
1323
|
case 1: {
|
|
1376
1324
|
const [num] = args;
|
|
1377
|
-
return (array
|
|
1325
|
+
return (array) => take(array, num);
|
|
1378
1326
|
}
|
|
1379
1327
|
}
|
|
1380
1328
|
}
|
|
@@ -1402,41 +1350,37 @@ export namespace Arr {
|
|
|
1402
1350
|
* console.log(result); // [4, 5]
|
|
1403
1351
|
* ```
|
|
1404
1352
|
*/
|
|
1405
|
-
export function takeLast<
|
|
1353
|
+
export function takeLast<
|
|
1354
|
+
Ar extends readonly unknown[],
|
|
1355
|
+
N extends SizeType.ArgArr,
|
|
1356
|
+
>(
|
|
1406
1357
|
array: Ar,
|
|
1407
1358
|
num: N,
|
|
1408
|
-
):
|
|
1409
|
-
|
|
1410
|
-
|
|
1359
|
+
): N extends SmallUint
|
|
1360
|
+
? List.TakeLast<N, Ar>
|
|
1361
|
+
: N extends SizeType.ArgArrPositive
|
|
1362
|
+
? Ar extends NonEmptyArray<unknown>
|
|
1363
|
+
? NonEmptyArray<Ar[number]>
|
|
1364
|
+
: readonly Ar[number][]
|
|
1365
|
+
: readonly Ar[number][];
|
|
1366
|
+
|
|
1367
|
+
export function takeLast<N extends SizeType.ArgArr>(
|
|
1411
1368
|
num: N,
|
|
1412
|
-
): <Ar extends readonly unknown[]>(
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
): <E>(array: NonEmptyArray<E>) => NonEmptyArray<E>;
|
|
1422
|
-
|
|
1423
|
-
export function takeLast<E>(
|
|
1424
|
-
array: readonly E[],
|
|
1425
|
-
num: SizeType.ArgArrNonNegative,
|
|
1426
|
-
): readonly E[];
|
|
1427
|
-
|
|
1428
|
-
export function takeLast(
|
|
1429
|
-
num: SizeType.ArgArrNonNegative,
|
|
1430
|
-
): <E>(array: readonly E[]) => readonly E[];
|
|
1369
|
+
): <Ar extends readonly unknown[]>(
|
|
1370
|
+
array: Ar,
|
|
1371
|
+
) => N extends SmallUint
|
|
1372
|
+
? List.TakeLast<N, Ar>
|
|
1373
|
+
: N extends SizeType.ArgArrPositive
|
|
1374
|
+
? Ar extends NonEmptyArray<unknown>
|
|
1375
|
+
? NonEmptyArray<Ar[number]>
|
|
1376
|
+
: readonly Ar[number][]
|
|
1377
|
+
: readonly Ar[number][];
|
|
1431
1378
|
|
|
1432
1379
|
export function takeLast<E>(
|
|
1433
1380
|
...args:
|
|
1434
|
-
| readonly [array: readonly E[], num: SizeType.
|
|
1435
|
-
| readonly [num: SizeType.
|
|
1436
|
-
):
|
|
1437
|
-
| readonly E[]
|
|
1438
|
-
| ((array: NonEmptyArray<E>) => NonEmptyArray<E>)
|
|
1439
|
-
| ((array: readonly E[]) => readonly E[]) {
|
|
1381
|
+
| readonly [array: readonly E[], num: SizeType.ArgArr]
|
|
1382
|
+
| readonly [num: SizeType.ArgArr]
|
|
1383
|
+
): readonly E[] | ((array: readonly E[]) => readonly E[]) {
|
|
1440
1384
|
switch (args.length) {
|
|
1441
1385
|
case 2: {
|
|
1442
1386
|
const [array, num] = args;
|
|
@@ -1444,7 +1388,7 @@ export namespace Arr {
|
|
|
1444
1388
|
}
|
|
1445
1389
|
case 1: {
|
|
1446
1390
|
const [num] = args;
|
|
1447
|
-
return (array
|
|
1391
|
+
return (array) => takeLast(array, num);
|
|
1448
1392
|
}
|
|
1449
1393
|
}
|
|
1450
1394
|
}
|
|
@@ -1472,41 +1416,26 @@ export namespace Arr {
|
|
|
1472
1416
|
* console.log(result); // [3, 4, 5]
|
|
1473
1417
|
* ```
|
|
1474
1418
|
*/
|
|
1475
|
-
export function skip<
|
|
1419
|
+
export function skip<
|
|
1420
|
+
Ar extends readonly unknown[],
|
|
1421
|
+
N extends SizeType.ArgArr,
|
|
1422
|
+
>(
|
|
1476
1423
|
array: Ar,
|
|
1477
1424
|
num: N,
|
|
1478
|
-
): List.Skip<N, Ar
|
|
1479
|
-
|
|
1480
|
-
export function skip<E>(
|
|
1481
|
-
array: NonEmptyArray<E>,
|
|
1482
|
-
num: SizeType.ArgArrPositive,
|
|
1483
|
-
): readonly E[];
|
|
1425
|
+
): N extends SmallUint ? List.Skip<N, Ar> : readonly Ar[number][];
|
|
1484
1426
|
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
num: SizeType.ArgArrNonNegative,
|
|
1488
|
-
): readonly E[];
|
|
1489
|
-
|
|
1490
|
-
export function skip<N extends SmallUint>(
|
|
1427
|
+
// curried version
|
|
1428
|
+
export function skip<N extends SizeType.ArgArr>(
|
|
1491
1429
|
num: N,
|
|
1492
|
-
): <Ar extends readonly unknown[]>(
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
num: SizeType.ArgArrPositive,
|
|
1496
|
-
): <E>(array: NonEmptyArray<E>) => readonly E[];
|
|
1497
|
-
|
|
1498
|
-
export function skip(
|
|
1499
|
-
num: SizeType.ArgArrNonNegative,
|
|
1500
|
-
): <E>(array: readonly E[]) => readonly E[];
|
|
1430
|
+
): <Ar extends readonly unknown[]>(
|
|
1431
|
+
array: Ar,
|
|
1432
|
+
) => N extends SmallUint ? List.Skip<N, Ar> : readonly Ar[number][];
|
|
1501
1433
|
|
|
1502
1434
|
export function skip<E>(
|
|
1503
1435
|
...args:
|
|
1504
|
-
| readonly [readonly E[], SizeType.
|
|
1505
|
-
| readonly [SizeType.
|
|
1506
|
-
):
|
|
1507
|
-
| readonly E[]
|
|
1508
|
-
| ((array: NonEmptyArray<E>) => readonly E[])
|
|
1509
|
-
| ((array: readonly E[]) => readonly E[]) {
|
|
1436
|
+
| readonly [readonly E[], SizeType.ArgArr]
|
|
1437
|
+
| readonly [SizeType.ArgArr]
|
|
1438
|
+
): readonly E[] | ((array: readonly E[]) => readonly E[]) {
|
|
1510
1439
|
switch (args.length) {
|
|
1511
1440
|
case 2: {
|
|
1512
1441
|
const [array, num] = args;
|
|
@@ -1514,7 +1443,7 @@ export namespace Arr {
|
|
|
1514
1443
|
}
|
|
1515
1444
|
case 1: {
|
|
1516
1445
|
const [num] = args;
|
|
1517
|
-
return (array
|
|
1446
|
+
return (array) => skip(array, num);
|
|
1518
1447
|
}
|
|
1519
1448
|
}
|
|
1520
1449
|
}
|
|
@@ -1542,28 +1471,25 @@ export namespace Arr {
|
|
|
1542
1471
|
* console.log(result); // [1, 2, 3]
|
|
1543
1472
|
* ```
|
|
1544
1473
|
*/
|
|
1545
|
-
export function skipLast<
|
|
1474
|
+
export function skipLast<
|
|
1475
|
+
Ar extends readonly unknown[],
|
|
1476
|
+
N extends SizeType.ArgArr,
|
|
1477
|
+
>(
|
|
1546
1478
|
array: Ar,
|
|
1547
1479
|
num: N,
|
|
1548
|
-
): List.SkipLast<N, Ar
|
|
1480
|
+
): N extends SmallUint ? List.SkipLast<N, Ar> : readonly Ar[number][];
|
|
1549
1481
|
|
|
1550
|
-
|
|
1482
|
+
// curried version
|
|
1483
|
+
export function skipLast<N extends SizeType.ArgArr>(
|
|
1551
1484
|
num: N,
|
|
1552
|
-
): <Ar extends readonly unknown[]>(
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
array: readonly E[],
|
|
1556
|
-
num: SizeType.ArgArrNonNegative,
|
|
1557
|
-
): readonly E[];
|
|
1558
|
-
|
|
1559
|
-
export function skipLast(
|
|
1560
|
-
num: SizeType.ArgArrNonNegative,
|
|
1561
|
-
): <E>(array: readonly E[]) => readonly E[];
|
|
1485
|
+
): <Ar extends readonly unknown[]>(
|
|
1486
|
+
array: Ar,
|
|
1487
|
+
) => N extends SmallUint ? List.SkipLast<N, Ar> : readonly Ar[number][];
|
|
1562
1488
|
|
|
1563
1489
|
export function skipLast<E>(
|
|
1564
1490
|
...args:
|
|
1565
|
-
| readonly [array: readonly E[], num: SizeType.
|
|
1566
|
-
| readonly [num: SizeType.
|
|
1491
|
+
| readonly [array: readonly E[], num: SizeType.ArgArr]
|
|
1492
|
+
| readonly [num: SizeType.ArgArr]
|
|
1567
1493
|
): readonly E[] | ((array: readonly E[]) => readonly E[]) {
|
|
1568
1494
|
switch (args.length) {
|
|
1569
1495
|
case 2: {
|
|
@@ -1572,13 +1498,91 @@ export namespace Arr {
|
|
|
1572
1498
|
}
|
|
1573
1499
|
case 1: {
|
|
1574
1500
|
const [num] = args;
|
|
1575
|
-
return (array
|
|
1501
|
+
return (array) => skipLast(array, num);
|
|
1576
1502
|
}
|
|
1577
1503
|
}
|
|
1578
1504
|
}
|
|
1579
1505
|
|
|
1580
1506
|
// modification (returns new array)
|
|
1581
1507
|
|
|
1508
|
+
/**
|
|
1509
|
+
* Returns a new tuple with the element at the specified index replaced.
|
|
1510
|
+
*
|
|
1511
|
+
* This operation is type-safe with compile-time index validation.
|
|
1512
|
+
* The resulting tuple type reflects that the element at the given index
|
|
1513
|
+
* may be either the new type or the original type.
|
|
1514
|
+
*
|
|
1515
|
+
* @template T - The type of the input tuple
|
|
1516
|
+
* @template N - The type of the new value to set
|
|
1517
|
+
* @param tpl - The input tuple
|
|
1518
|
+
* @param index - The index to update (must be valid for the tuple length)
|
|
1519
|
+
* @param newValue - The new value to place at the index
|
|
1520
|
+
* @returns A new tuple with the updated element
|
|
1521
|
+
*
|
|
1522
|
+
* @example
|
|
1523
|
+
* ```typescript
|
|
1524
|
+
* // Basic usage
|
|
1525
|
+
* const tpl = ['a', 'b', 'c'] as const;
|
|
1526
|
+
* const updated = Arr.set(tpl, 1, 'B'); // readonly ['a', 'B', 'c']
|
|
1527
|
+
*
|
|
1528
|
+
* // Type changes are reflected
|
|
1529
|
+
* const mixed = [1, 'hello', true] as const;
|
|
1530
|
+
* const withNumber = Arr.set(mixed, 1, 42);
|
|
1531
|
+
* // readonly [1, 42 | 'hello', true]
|
|
1532
|
+
*
|
|
1533
|
+
* // Compile-time index validation
|
|
1534
|
+
* const short = [1, 2] as const;
|
|
1535
|
+
* // Arr.set(short, 2, 3); // Error: index 2 is out of bounds
|
|
1536
|
+
*
|
|
1537
|
+
* // Different value types
|
|
1538
|
+
* const nums = [1, 2, 3] as const;
|
|
1539
|
+
* const withString = Arr.set(nums, 0, 'first');
|
|
1540
|
+
* // readonly ['first' | 1, 2, 3]
|
|
1541
|
+
* ```
|
|
1542
|
+
*/
|
|
1543
|
+
export function set<
|
|
1544
|
+
const Ar extends readonly unknown[],
|
|
1545
|
+
const V = Ar[number],
|
|
1546
|
+
>(
|
|
1547
|
+
array: Ar,
|
|
1548
|
+
index: ArgArrayIndex<Ar>,
|
|
1549
|
+
newValue: V,
|
|
1550
|
+
): IsFixedLengthList<Ar> extends true
|
|
1551
|
+
? Readonly<{ [K in keyof Ar]: Ar[K] | V }>
|
|
1552
|
+
: Ar extends NonEmptyArray<unknown>
|
|
1553
|
+
? NonEmptyArray<Ar[number] | V>
|
|
1554
|
+
: readonly (Ar[number] | V)[];
|
|
1555
|
+
|
|
1556
|
+
// curried version
|
|
1557
|
+
export function set<const V>(
|
|
1558
|
+
index: SizeType.ArgArr,
|
|
1559
|
+
newValue: V,
|
|
1560
|
+
): <const Ar extends readonly unknown[]>(
|
|
1561
|
+
array: Ar,
|
|
1562
|
+
) => IsFixedLengthList<Ar> extends true
|
|
1563
|
+
? Readonly<{ [K in keyof Ar]: Ar[K] | V }>
|
|
1564
|
+
: Ar extends NonEmptyArray<unknown>
|
|
1565
|
+
? NonEmptyArray<Ar[number] | V>
|
|
1566
|
+
: readonly (Ar[number] | V)[];
|
|
1567
|
+
|
|
1568
|
+
export function set<E, const V = E>(
|
|
1569
|
+
...args:
|
|
1570
|
+
| readonly [array: readonly E[], index: SizeType.ArgArr, newValue: V]
|
|
1571
|
+
| readonly [index: SizeType.ArgArr, newValue: V]
|
|
1572
|
+
): readonly (E | V)[] | ((array: readonly E[]) => readonly (E | V)[]) {
|
|
1573
|
+
switch (args.length) {
|
|
1574
|
+
case 3: {
|
|
1575
|
+
const [array, index, newValue] = args;
|
|
1576
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
1577
|
+
return (array as (E | V)[]).with(index, newValue);
|
|
1578
|
+
}
|
|
1579
|
+
case 2: {
|
|
1580
|
+
const [index, newValue] = args;
|
|
1581
|
+
return (array) => set(array, index, newValue);
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1582
1586
|
/**
|
|
1583
1587
|
* Returns a new array with the element at the specified index updated by a function.
|
|
1584
1588
|
*
|
|
@@ -1600,9 +1604,9 @@ export namespace Arr {
|
|
|
1600
1604
|
* updater, returns a reusable function that can be applied to arrays.
|
|
1601
1605
|
*
|
|
1602
1606
|
* @template E The type of elements in the original array.
|
|
1603
|
-
* @template
|
|
1607
|
+
* @template V The type of the value returned by the updater function.
|
|
1604
1608
|
* @param array The input array to update. Can be any readonly array.
|
|
1605
|
-
* @param index The index of the element to update. Must be a non-negative {@link SizeType.
|
|
1609
|
+
* @param index The index of the element to update. Must be a non-negative {@link SizeType.ArgArr}.
|
|
1606
1610
|
* - **Valid range:** `0 <= index < array.length`
|
|
1607
1611
|
* - **Out of bounds:** Returns original array unchanged
|
|
1608
1612
|
* - **Negative values:** Not allowed by type system (non-negative constraint)
|
|
@@ -1730,40 +1734,52 @@ export namespace Arr {
|
|
|
1730
1734
|
* ```
|
|
1731
1735
|
*
|
|
1732
1736
|
* @see {@link Array.prototype.with} for the native method with different error handling
|
|
1733
|
-
* @see {@link SizeType.
|
|
1737
|
+
* @see {@link SizeType.ArgArr} for the index type constraint
|
|
1734
1738
|
* @see Immutable update patterns for functional programming approaches
|
|
1735
1739
|
*/
|
|
1736
|
-
export function toUpdated<
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1740
|
+
export function toUpdated<
|
|
1741
|
+
const Ar extends readonly unknown[],
|
|
1742
|
+
const V = Ar[number],
|
|
1743
|
+
>(
|
|
1744
|
+
array: Ar,
|
|
1745
|
+
index: ArgArrayIndex<Ar>,
|
|
1746
|
+
updater: (prev: Ar[number]) => V,
|
|
1747
|
+
): IsFixedLengthList<Ar> extends true
|
|
1748
|
+
? Readonly<{ [K in keyof Ar]: Ar[K] | V }>
|
|
1749
|
+
: Ar extends NonEmptyArray<unknown>
|
|
1750
|
+
? NonEmptyArray<Ar[number] | V>
|
|
1751
|
+
: readonly (Ar[number] | V)[];
|
|
1752
|
+
|
|
1753
|
+
// curried version
|
|
1754
|
+
export function toUpdated<E, const V = E>(
|
|
1755
|
+
index: SizeType.ArgArr,
|
|
1756
|
+
updater: (prev: E) => V,
|
|
1757
|
+
): <const Ar extends readonly E[]>(
|
|
1758
|
+
array: Ar,
|
|
1759
|
+
) => IsFixedLengthList<Ar> extends true
|
|
1760
|
+
? Readonly<{ [K in keyof Ar]: Ar[K] | V }>
|
|
1761
|
+
: Ar extends NonEmptyArray<unknown>
|
|
1762
|
+
? NonEmptyArray<Ar[number] | V>
|
|
1763
|
+
: readonly (Ar[number] | V)[];
|
|
1746
1764
|
|
|
1747
|
-
export function toUpdated<E,
|
|
1765
|
+
export function toUpdated<E, V = E>(
|
|
1748
1766
|
...args:
|
|
1749
1767
|
| readonly [
|
|
1750
1768
|
array: readonly E[],
|
|
1751
|
-
index: SizeType.
|
|
1752
|
-
updater: (prev: E) =>
|
|
1769
|
+
index: SizeType.ArgArr,
|
|
1770
|
+
updater: (prev: E) => V,
|
|
1753
1771
|
]
|
|
1754
|
-
| readonly [index: SizeType.
|
|
1755
|
-
): readonly (E |
|
|
1772
|
+
| readonly [index: SizeType.ArgArr, updater: (prev: E) => V]
|
|
1773
|
+
): readonly (E | V)[] | ((array: readonly E[]) => readonly (E | V)[]) {
|
|
1756
1774
|
switch (args.length) {
|
|
1757
1775
|
case 3: {
|
|
1758
1776
|
const [array, index, updater] = args;
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
: // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unsafe-type-assertion
|
|
1762
|
-
(array as (E | U)[]).with(index, updater(array[index]!));
|
|
1777
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unsafe-type-assertion
|
|
1778
|
+
return (array as (E | V)[]).with(index, updater(array[index]!));
|
|
1763
1779
|
}
|
|
1764
1780
|
case 2: {
|
|
1765
1781
|
const [index, updater] = args;
|
|
1766
|
-
return (array
|
|
1782
|
+
return (array) => toUpdated(array, index, updater);
|
|
1767
1783
|
}
|
|
1768
1784
|
}
|
|
1769
1785
|
}
|
|
@@ -1787,25 +1803,35 @@ export namespace Arr {
|
|
|
1787
1803
|
* console.log(result); // [99, 1, 2, 3]
|
|
1788
1804
|
* ```
|
|
1789
1805
|
*/
|
|
1790
|
-
export function toInserted<
|
|
1791
|
-
|
|
1792
|
-
|
|
1806
|
+
export function toInserted<
|
|
1807
|
+
Ar extends readonly unknown[],
|
|
1808
|
+
const V = Ar[number],
|
|
1809
|
+
>(
|
|
1810
|
+
array: Ar,
|
|
1811
|
+
index: ArgArrayIndexWithNegative<Ar>,
|
|
1793
1812
|
newValue: V,
|
|
1794
|
-
):
|
|
1813
|
+
): IsFixedLengthList<Ar> extends true
|
|
1814
|
+
? ArrayOfLength<CastToNumber<Increment<Ar['length']>>, Ar[number] | V>
|
|
1815
|
+
: NonEmptyArray<Ar[number] | V>;
|
|
1795
1816
|
|
|
1796
|
-
|
|
1797
|
-
|
|
1817
|
+
// curried version
|
|
1818
|
+
export function toInserted<const V>(
|
|
1819
|
+
index: SizeType.ArgArrWithNegative,
|
|
1798
1820
|
newValue: V,
|
|
1799
|
-
):
|
|
1821
|
+
): <Ar extends readonly unknown[]>(
|
|
1822
|
+
array: Ar,
|
|
1823
|
+
) => IsFixedLengthList<Ar> extends true
|
|
1824
|
+
? ArrayOfLength<CastToNumber<Increment<Ar['length']>>, Ar[number] | V>
|
|
1825
|
+
: NonEmptyArray<Ar[number] | V>;
|
|
1800
1826
|
|
|
1801
1827
|
export function toInserted<E, const V = E>(
|
|
1802
1828
|
...args:
|
|
1803
1829
|
| readonly [
|
|
1804
1830
|
array: readonly E[],
|
|
1805
|
-
index: SizeType.
|
|
1831
|
+
index: SizeType.ArgArrWithNegative,
|
|
1806
1832
|
newValue: V,
|
|
1807
1833
|
]
|
|
1808
|
-
| readonly [index: SizeType.
|
|
1834
|
+
| readonly [index: SizeType.ArgArrWithNegative, newValue: V]
|
|
1809
1835
|
): NonEmptyArray<E | V> | ((array: readonly E[]) => NonEmptyArray<E | V>) {
|
|
1810
1836
|
switch (args.length) {
|
|
1811
1837
|
case 3: {
|
|
@@ -1819,11 +1845,13 @@ export namespace Arr {
|
|
|
1819
1845
|
}
|
|
1820
1846
|
case 2: {
|
|
1821
1847
|
const [index, newValue] = args;
|
|
1822
|
-
return (array
|
|
1848
|
+
return (array) => toInserted(array, index, newValue);
|
|
1823
1849
|
}
|
|
1824
1850
|
}
|
|
1825
1851
|
}
|
|
1826
1852
|
|
|
1853
|
+
type CastToNumber<T> = T extends number ? T : never;
|
|
1854
|
+
|
|
1827
1855
|
/**
|
|
1828
1856
|
* Returns a new array with the element at the specified index removed.
|
|
1829
1857
|
* If index is out of bounds, `toSpliced` handles this (usually by returning a copy).
|
|
@@ -1842,19 +1870,19 @@ export namespace Arr {
|
|
|
1842
1870
|
* console.log(result); // [20, 30]
|
|
1843
1871
|
* ```
|
|
1844
1872
|
*/
|
|
1845
|
-
export function toRemoved<
|
|
1846
|
-
array:
|
|
1847
|
-
index:
|
|
1848
|
-
): readonly
|
|
1873
|
+
export function toRemoved<Ar extends readonly unknown[]>(
|
|
1874
|
+
array: Ar,
|
|
1875
|
+
index: ArgArrayIndexWithNegative<Ar>,
|
|
1876
|
+
): readonly Ar[number][];
|
|
1849
1877
|
|
|
1850
1878
|
export function toRemoved(
|
|
1851
|
-
index: SizeType.
|
|
1879
|
+
index: SizeType.ArgArrWithNegative,
|
|
1852
1880
|
): <E>(array: readonly E[]) => readonly E[];
|
|
1853
1881
|
|
|
1854
1882
|
export function toRemoved<E>(
|
|
1855
1883
|
...args:
|
|
1856
|
-
| readonly [array: readonly E[], index: SizeType.
|
|
1857
|
-
| readonly [index: SizeType.
|
|
1884
|
+
| readonly [array: readonly E[], index: SizeType.ArgArrWithNegative]
|
|
1885
|
+
| readonly [index: SizeType.ArgArrWithNegative]
|
|
1858
1886
|
): readonly E[] | ((array: readonly E[]) => readonly E[]) {
|
|
1859
1887
|
switch (args.length) {
|
|
1860
1888
|
case 2: {
|
|
@@ -1863,7 +1891,7 @@ export namespace Arr {
|
|
|
1863
1891
|
}
|
|
1864
1892
|
case 1: {
|
|
1865
1893
|
const [index] = args;
|
|
1866
|
-
return (array
|
|
1894
|
+
return (array) => toRemoved(array, index);
|
|
1867
1895
|
}
|
|
1868
1896
|
}
|
|
1869
1897
|
}
|
|
@@ -1962,28 +1990,54 @@ export namespace Arr {
|
|
|
1962
1990
|
}
|
|
1963
1991
|
|
|
1964
1992
|
/**
|
|
1965
|
-
*
|
|
1966
|
-
*
|
|
1967
|
-
*
|
|
1968
|
-
*
|
|
1969
|
-
*
|
|
1970
|
-
*
|
|
1993
|
+
* Creates a new array of the same length filled with a specified value.
|
|
1994
|
+
*
|
|
1995
|
+
* This function replaces all elements in the array with the provided value,
|
|
1996
|
+
* maintaining the original array's length and structure. It provides type-safe
|
|
1997
|
+
* array filling with precise return types.
|
|
1998
|
+
*
|
|
1999
|
+
* @template Ar The exact type of the input array.
|
|
2000
|
+
* @template V The type of the fill value.
|
|
2001
|
+
* @param array The array to fill.
|
|
2002
|
+
* @param value The value to fill the array with.
|
|
2003
|
+
* @returns A new array of the same length filled with the specified value:
|
|
2004
|
+
* - For fixed-length arrays: returns `ArrayOfLength<Ar['length'], V>`
|
|
2005
|
+
* - For non-empty arrays: returns `NonEmptyArray<V>`
|
|
2006
|
+
* - For general arrays: returns `readonly V[]`
|
|
2007
|
+
*
|
|
1971
2008
|
* @example
|
|
1972
2009
|
* ```typescript
|
|
1973
2010
|
* // Regular usage
|
|
1974
|
-
* const
|
|
1975
|
-
* const
|
|
1976
|
-
* console.log(result); // [1, 0, 0, 0, 5]
|
|
2011
|
+
* const numbers = [1, 2, 3, 4, 5];
|
|
2012
|
+
* const zeros = Arr.toFilled(numbers, 0); // [0, 0, 0, 0, 0]
|
|
1977
2013
|
*
|
|
1978
2014
|
* // Curried usage for pipe composition
|
|
1979
|
-
* const
|
|
1980
|
-
* const
|
|
1981
|
-
* console.log(result2); // [1, 0, 0, 4]
|
|
2015
|
+
* const fillWithX = Arr.toFilled('X');
|
|
2016
|
+
* const result = pipe(['a', 'b', 'c']).map(fillWithX).value; // ['X', 'X', 'X']
|
|
1982
2017
|
* ```
|
|
2018
|
+
*
|
|
2019
|
+
* @see {@link toRangeFilled} for filling only a specific range
|
|
2020
|
+
* @see {@link create} for creating new arrays filled with a value
|
|
1983
2021
|
*/
|
|
1984
|
-
export function toFilled<
|
|
1985
|
-
|
|
1986
|
-
|
|
2022
|
+
export function toFilled<Ar extends readonly unknown[], const V>(
|
|
2023
|
+
array: Ar,
|
|
2024
|
+
value: V,
|
|
2025
|
+
): IsFixedLengthList<Ar> extends true
|
|
2026
|
+
? ArrayOfLength<Ar['length'], V>
|
|
2027
|
+
: Ar extends NonEmptyArray<unknown>
|
|
2028
|
+
? NonEmptyArray<V>
|
|
2029
|
+
: readonly V[];
|
|
2030
|
+
|
|
2031
|
+
// curried version
|
|
2032
|
+
export function toFilled<const V>(
|
|
2033
|
+
value: V,
|
|
2034
|
+
): <Ar extends readonly unknown[]>(
|
|
2035
|
+
array: Ar,
|
|
2036
|
+
) => IsFixedLengthList<Ar> extends true
|
|
2037
|
+
? ArrayOfLength<Ar['length'], V>
|
|
2038
|
+
: Ar extends NonEmptyArray<unknown>
|
|
2039
|
+
? NonEmptyArray<V>
|
|
2040
|
+
: readonly V[];
|
|
1987
2041
|
|
|
1988
2042
|
export function toFilled<E>(
|
|
1989
2043
|
...args: readonly [array: readonly E[], value: E] | readonly [value: E]
|
|
@@ -1991,9 +2045,7 @@ export namespace Arr {
|
|
|
1991
2045
|
switch (args.length) {
|
|
1992
2046
|
case 2: {
|
|
1993
2047
|
const [array, value] = args;
|
|
1994
|
-
|
|
1995
|
-
cp.fill(value);
|
|
1996
|
-
return cp;
|
|
2048
|
+
return create(asPositiveUint32(array.length), value);
|
|
1997
2049
|
}
|
|
1998
2050
|
case 1: {
|
|
1999
2051
|
const [value] = args;
|
|
@@ -2002,33 +2054,86 @@ export namespace Arr {
|
|
|
2002
2054
|
}
|
|
2003
2055
|
}
|
|
2004
2056
|
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2057
|
+
/**
|
|
2058
|
+
* Creates a new array with a specific range filled with a specified value.
|
|
2059
|
+
*
|
|
2060
|
+
* This function fills only the specified range of indices with the provided value,
|
|
2061
|
+
* leaving other elements unchanged. It provides type-safe range filling with
|
|
2062
|
+
* precise return types.
|
|
2063
|
+
*
|
|
2064
|
+
* @template Ar The exact type of the input array.
|
|
2065
|
+
* @template V The type of the fill value.
|
|
2066
|
+
* @param array The array to fill a range of.
|
|
2067
|
+
* @param value The value to fill the range with.
|
|
2068
|
+
* @param fillRange A tuple containing [start, end] indices for the range to fill.
|
|
2069
|
+
* @returns A new array with the specified range filled:
|
|
2070
|
+
* - For fixed-length arrays: returns `ArrayOfLength<Ar['length'], V | Ar[number]>`
|
|
2071
|
+
* - For non-empty arrays: returns `NonEmptyArray<V | Ar[number]>`
|
|
2072
|
+
* - For general arrays: returns `readonly (V | Ar[number])[]`
|
|
2073
|
+
*
|
|
2074
|
+
* @example
|
|
2075
|
+
* ```typescript
|
|
2076
|
+
* // Regular usage
|
|
2077
|
+
* const numbers = [1, 2, 3, 4, 5];
|
|
2078
|
+
* const result = Arr.toRangeFilled(numbers, 0, [1, 4]); // [1, 0, 0, 0, 5]
|
|
2079
|
+
*
|
|
2080
|
+
* // Curried usage for pipe composition
|
|
2081
|
+
* const fillMiddleWithX = Arr.toRangeFilled('X', [1, 3]);
|
|
2082
|
+
* const result2 = pipe(['a', 'b', 'c', 'd']).map(fillMiddleWithX).value; // ['a', 'X', 'X', 'd']
|
|
2083
|
+
* ```
|
|
2084
|
+
*
|
|
2085
|
+
* @see {@link toFilled} for filling the entire array
|
|
2086
|
+
*/
|
|
2087
|
+
export function toRangeFilled<Ar extends readonly unknown[], const V>(
|
|
2088
|
+
array: Ar,
|
|
2089
|
+
value: V,
|
|
2090
|
+
fillRange: readonly [
|
|
2091
|
+
start: ArgArrayIndexWithNegative<Ar>,
|
|
2092
|
+
end: ArgArrayIndexWithNegative<Ar>,
|
|
2093
|
+
],
|
|
2094
|
+
): IsFixedLengthList<Ar> extends true
|
|
2095
|
+
? ArrayOfLength<Ar['length'], V | Ar[number]>
|
|
2096
|
+
: Ar extends NonEmptyArray<unknown>
|
|
2097
|
+
? NonEmptyArray<V | Ar[number]>
|
|
2098
|
+
: readonly (V | Ar[number])[];
|
|
2099
|
+
|
|
2100
|
+
// curried version
|
|
2101
|
+
export function toRangeFilled<const V>(
|
|
2102
|
+
value: V,
|
|
2103
|
+
fillRange: readonly [
|
|
2104
|
+
start: SizeType.ArgArrWithNegative,
|
|
2105
|
+
end: SizeType.ArgArrWithNegative,
|
|
2106
|
+
],
|
|
2107
|
+
): <Ar extends readonly unknown[]>(
|
|
2108
|
+
array: Ar,
|
|
2109
|
+
) => IsFixedLengthList<Ar> extends true
|
|
2110
|
+
? ArrayOfLength<Ar['length'], V | Ar[number]>
|
|
2111
|
+
: Ar extends NonEmptyArray<unknown>
|
|
2112
|
+
? NonEmptyArray<V | Ar[number]>
|
|
2113
|
+
: readonly (V | Ar[number])[];
|
|
2015
2114
|
|
|
2016
|
-
export function toRangeFilled<E>(
|
|
2115
|
+
export function toRangeFilled<E, const V>(
|
|
2017
2116
|
...args:
|
|
2018
2117
|
| readonly [
|
|
2019
2118
|
array: readonly E[],
|
|
2020
|
-
value:
|
|
2021
|
-
fillRange: readonly [
|
|
2119
|
+
value: V,
|
|
2120
|
+
fillRange: readonly [
|
|
2121
|
+
start: SizeType.ArgArrWithNegative,
|
|
2122
|
+
end: SizeType.ArgArrWithNegative,
|
|
2123
|
+
],
|
|
2022
2124
|
]
|
|
2023
2125
|
| readonly [
|
|
2024
|
-
value:
|
|
2025
|
-
fillRange: readonly [
|
|
2126
|
+
value: V,
|
|
2127
|
+
fillRange: readonly [
|
|
2128
|
+
start: SizeType.ArgArrWithNegative,
|
|
2129
|
+
end: SizeType.ArgArrWithNegative,
|
|
2130
|
+
],
|
|
2026
2131
|
]
|
|
2027
|
-
): readonly E[] | ((array: readonly E[]) => readonly E[]) {
|
|
2132
|
+
): readonly (E | V)[] | ((array: readonly E[]) => readonly (E | V)[]) {
|
|
2028
2133
|
switch (args.length) {
|
|
2029
2134
|
case 3: {
|
|
2030
2135
|
const [array, value, [start, end]] = args;
|
|
2031
|
-
const cp = castMutable(copy(array));
|
|
2136
|
+
const cp: (E | V)[] = castMutable(copy(array));
|
|
2032
2137
|
cp.fill(value, start, end);
|
|
2033
2138
|
return cp;
|
|
2034
2139
|
}
|
|
@@ -2078,10 +2183,15 @@ export namespace Arr {
|
|
|
2078
2183
|
* @see {@link indexOf} for finding elements by equality
|
|
2079
2184
|
* @see {@link Optional} for working with the returned Optional values
|
|
2080
2185
|
*/
|
|
2081
|
-
export function find<E>(
|
|
2186
|
+
export function find<E, F extends E>(
|
|
2082
2187
|
array: readonly E[],
|
|
2083
|
-
predicate: (value: E, index: SizeType.Arr, arr: readonly E[]) =>
|
|
2084
|
-
): Optional<
|
|
2188
|
+
predicate: (value: E, index: SizeType.Arr, arr: readonly E[]) => value is F,
|
|
2189
|
+
): Optional<F>;
|
|
2190
|
+
|
|
2191
|
+
export function find<Ar extends readonly unknown[]>(
|
|
2192
|
+
array: Ar,
|
|
2193
|
+
predicate: (value: Ar[number], index: ArrayIndex<Ar>, arr: Ar) => boolean,
|
|
2194
|
+
): Optional<Ar[number]>;
|
|
2085
2195
|
|
|
2086
2196
|
export function find<E>(
|
|
2087
2197
|
predicate: (value: E, index: SizeType.Arr, arr: readonly E[]) => boolean,
|
|
@@ -2110,9 +2220,114 @@ export namespace Arr {
|
|
|
2110
2220
|
const [array, predicate] = args;
|
|
2111
2221
|
const foundIndex = array.findIndex(
|
|
2112
2222
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
2113
|
-
predicate as (
|
|
2223
|
+
predicate as () => boolean,
|
|
2224
|
+
);
|
|
2225
|
+
|
|
2226
|
+
expectType<
|
|
2227
|
+
Parameters<typeof array.findIndex>[0],
|
|
2228
|
+
(value: E, index: number, arr: readonly E[]) => unknown
|
|
2229
|
+
>('=');
|
|
2230
|
+
|
|
2231
|
+
expectType<
|
|
2232
|
+
typeof predicate,
|
|
2233
|
+
(value: E, index: SizeType.Arr, arr: readonly E[]) => boolean
|
|
2234
|
+
>('=');
|
|
2235
|
+
|
|
2236
|
+
return foundIndex === -1
|
|
2237
|
+
? Optional.none
|
|
2238
|
+
: // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
2239
|
+
Optional.some(array[foundIndex]!);
|
|
2240
|
+
}
|
|
2241
|
+
case 1: {
|
|
2242
|
+
const [predicate] = args;
|
|
2243
|
+
|
|
2244
|
+
expectType<
|
|
2245
|
+
typeof predicate,
|
|
2246
|
+
(value: E, index: SizeType.Arr, arr: readonly E[]) => boolean
|
|
2247
|
+
>('=');
|
|
2248
|
+
|
|
2249
|
+
return (array) => find(array, predicate);
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
|
|
2254
|
+
/**
|
|
2255
|
+
* Returns the last element in an array that satisfies a predicate function.
|
|
2256
|
+
*
|
|
2257
|
+
* This function searches from the end of the array and returns an Optional containing
|
|
2258
|
+
* the first element found that satisfies the predicate, or None if no such element exists.
|
|
2259
|
+
*
|
|
2260
|
+
* @template Ar The exact type of the input array.
|
|
2261
|
+
* @template E The type of elements in the array.
|
|
2262
|
+
* @param array The array to search.
|
|
2263
|
+
* @param predicate A function that tests each element.
|
|
2264
|
+
* @returns An Optional containing the found element, or None if no element satisfies the predicate.
|
|
2265
|
+
*
|
|
2266
|
+
* @example
|
|
2267
|
+
* ```typescript
|
|
2268
|
+
* // Direct usage
|
|
2269
|
+
* const numbers = [1, 2, 3, 4, 5];
|
|
2270
|
+
* const lastEven = Arr.findLast(numbers, n => n % 2 === 0); // Optional.some(4)
|
|
2271
|
+
*
|
|
2272
|
+
* // Curried usage
|
|
2273
|
+
* const isPositive = (n: number) => n > 0;
|
|
2274
|
+
* const findLastPositive = Arr.findLast(isPositive);
|
|
2275
|
+
* const result = findLastPositive([-1, 2, -3, 4]); // Optional.some(4)
|
|
2276
|
+
*
|
|
2277
|
+
* // No match
|
|
2278
|
+
* const noMatch = Arr.findLast([1, 3, 5], n => n % 2 === 0); // Optional.none
|
|
2279
|
+
* ```
|
|
2280
|
+
*/
|
|
2281
|
+
export function findLast<E, F extends E>(
|
|
2282
|
+
array: readonly E[],
|
|
2283
|
+
predicate: (value: E, index: SizeType.Arr, arr: readonly E[]) => value is F,
|
|
2284
|
+
): Optional<F>;
|
|
2285
|
+
|
|
2286
|
+
export function findLast<Ar extends readonly unknown[]>(
|
|
2287
|
+
array: Ar,
|
|
2288
|
+
predicate: (value: Ar[number], index: ArrayIndex<Ar>, arr: Ar) => boolean,
|
|
2289
|
+
): Optional<Ar[number]>;
|
|
2290
|
+
|
|
2291
|
+
export function findLast<E>(
|
|
2292
|
+
predicate: (value: E, index: SizeType.Arr, arr: readonly E[]) => boolean,
|
|
2293
|
+
): (array: readonly E[]) => Optional<E>;
|
|
2294
|
+
|
|
2295
|
+
export function findLast<E>(
|
|
2296
|
+
...args:
|
|
2297
|
+
| readonly [
|
|
2298
|
+
array: readonly E[],
|
|
2299
|
+
predicate: (
|
|
2300
|
+
value: E,
|
|
2301
|
+
index: SizeType.Arr,
|
|
2302
|
+
arr: readonly E[],
|
|
2303
|
+
) => boolean,
|
|
2304
|
+
]
|
|
2305
|
+
| readonly [
|
|
2306
|
+
predicate: (
|
|
2307
|
+
value: E,
|
|
2308
|
+
index: SizeType.Arr,
|
|
2309
|
+
arr: readonly E[],
|
|
2310
|
+
) => boolean,
|
|
2311
|
+
]
|
|
2312
|
+
): Optional<E> | ((array: readonly E[]) => Optional<E>) {
|
|
2313
|
+
switch (args.length) {
|
|
2314
|
+
case 2: {
|
|
2315
|
+
const [array, predicate] = args;
|
|
2316
|
+
const foundIndex = array.findLastIndex(
|
|
2317
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
2318
|
+
predicate as () => boolean,
|
|
2114
2319
|
);
|
|
2115
2320
|
|
|
2321
|
+
expectType<
|
|
2322
|
+
Parameters<typeof array.findIndex>[0],
|
|
2323
|
+
(value: E, index: number, arr: readonly E[]) => unknown
|
|
2324
|
+
>('=');
|
|
2325
|
+
|
|
2326
|
+
expectType<
|
|
2327
|
+
typeof predicate,
|
|
2328
|
+
(value: E, index: SizeType.Arr, arr: readonly E[]) => boolean
|
|
2329
|
+
>('=');
|
|
2330
|
+
|
|
2116
2331
|
return foundIndex === -1
|
|
2117
2332
|
? Optional.none
|
|
2118
2333
|
: // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
@@ -2120,7 +2335,13 @@ export namespace Arr {
|
|
|
2120
2335
|
}
|
|
2121
2336
|
case 1: {
|
|
2122
2337
|
const [predicate] = args;
|
|
2123
|
-
|
|
2338
|
+
|
|
2339
|
+
expectType<
|
|
2340
|
+
typeof predicate,
|
|
2341
|
+
(value: E, index: SizeType.Arr, arr: readonly E[]) => boolean
|
|
2342
|
+
>('=');
|
|
2343
|
+
|
|
2344
|
+
return (array) => findLast(array, predicate);
|
|
2124
2345
|
}
|
|
2125
2346
|
}
|
|
2126
2347
|
}
|
|
@@ -2230,22 +2451,32 @@ export namespace Arr {
|
|
|
2230
2451
|
* @see {@link lastIndexOf} for finding the last occurrence
|
|
2231
2452
|
* @see {@link Optional} for working with the returned Optional values
|
|
2232
2453
|
*/
|
|
2233
|
-
export function findIndex<
|
|
2234
|
-
array:
|
|
2235
|
-
predicate: (value:
|
|
2236
|
-
):
|
|
2454
|
+
export function findIndex<Ar extends readonly unknown[]>(
|
|
2455
|
+
array: Ar,
|
|
2456
|
+
predicate: (value: Ar[number], index: ArrayIndex<Ar>, arr: Ar) => boolean,
|
|
2457
|
+
): ArrayIndex<Ar> | -1;
|
|
2237
2458
|
|
|
2238
2459
|
export function findIndex<E>(
|
|
2239
|
-
predicate: (value: E, index: SizeType.Arr) => boolean,
|
|
2460
|
+
predicate: (value: E, index: SizeType.Arr, arr: readonly E[]) => boolean,
|
|
2240
2461
|
): (array: readonly E[]) => SizeType.Arr | -1;
|
|
2241
2462
|
|
|
2242
2463
|
export function findIndex<E>(
|
|
2243
2464
|
...args:
|
|
2244
2465
|
| readonly [
|
|
2245
2466
|
array: readonly E[],
|
|
2246
|
-
predicate: (
|
|
2467
|
+
predicate: (
|
|
2468
|
+
value: E,
|
|
2469
|
+
index: SizeType.Arr,
|
|
2470
|
+
arr: readonly E[],
|
|
2471
|
+
) => boolean,
|
|
2472
|
+
]
|
|
2473
|
+
| readonly [
|
|
2474
|
+
predicate: (
|
|
2475
|
+
value: E,
|
|
2476
|
+
index: SizeType.Arr,
|
|
2477
|
+
arr: readonly E[],
|
|
2478
|
+
) => boolean,
|
|
2247
2479
|
]
|
|
2248
|
-
| readonly [predicate: (value: E, index: SizeType.Arr) => boolean]
|
|
2249
2480
|
): SizeType.Arr | -1 | ((array: readonly E[]) => SizeType.Arr | -1) {
|
|
2250
2481
|
switch (args.length) {
|
|
2251
2482
|
case 2: {
|
|
@@ -2259,7 +2490,141 @@ export namespace Arr {
|
|
|
2259
2490
|
}
|
|
2260
2491
|
case 1: {
|
|
2261
2492
|
const [predicate] = args;
|
|
2262
|
-
return (array
|
|
2493
|
+
return (array) => findIndex(array, predicate);
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
}
|
|
2497
|
+
|
|
2498
|
+
/**
|
|
2499
|
+
* Safely finds the index of the last element in an array that satisfies a predicate function.
|
|
2500
|
+
*
|
|
2501
|
+
* This function provides type-safe index searching with no risk of runtime errors. It searches
|
|
2502
|
+
* from the end of the array backwards and returns the index of the last element that matches
|
|
2503
|
+
* the predicate, or -1 if no element is found. The returned index is branded as `SizeType.Arr`
|
|
2504
|
+
* for type safety.
|
|
2505
|
+
*
|
|
2506
|
+
* **Curried Usage:** This function supports currying - when called with only a predicate,
|
|
2507
|
+
* it returns a function that can be applied to arrays, making it ideal for functional composition.
|
|
2508
|
+
*
|
|
2509
|
+
* @template Ar The exact type of the input array, used for precise return type inference.
|
|
2510
|
+
* @template E The type of elements in the array.
|
|
2511
|
+
* @param array The array to search through (when using direct call syntax).
|
|
2512
|
+
* @param predicate A function that tests each element. Called with:
|
|
2513
|
+
* - `value`: The current element being tested
|
|
2514
|
+
* - `index`: The index of the current element (branded as `SizeType.Arr`)
|
|
2515
|
+
* - `arr`: The array being searched
|
|
2516
|
+
* @returns The index of the last matching element as `SizeType.Arr`, or -1 if no element satisfies the predicate.
|
|
2517
|
+
*
|
|
2518
|
+
* @example
|
|
2519
|
+
* ```typescript
|
|
2520
|
+
* // Basic last index finding
|
|
2521
|
+
* const fruits = ['apple', 'banana', 'cherry', 'banana'];
|
|
2522
|
+
* const lastBananaIndex = Arr.findLastIndex(fruits, fruit => fruit === 'banana');
|
|
2523
|
+
* console.log(lastBananaIndex); // 3 - index of last 'banana'
|
|
2524
|
+
*
|
|
2525
|
+
* // Finding with complex conditions
|
|
2526
|
+
* const numbers = [1, 5, 10, 15, 20, 10, 5];
|
|
2527
|
+
* const lastLargeIndex = Arr.findLastIndex(numbers, (value, index) =>
|
|
2528
|
+
* value > 8 && index < 5
|
|
2529
|
+
* );
|
|
2530
|
+
* console.log(lastLargeIndex); // 3 - index of last value > 8 before index 5 (15)
|
|
2531
|
+
*
|
|
2532
|
+
* // Finding objects by property
|
|
2533
|
+
* const users = [
|
|
2534
|
+
* { id: 1, active: true },
|
|
2535
|
+
* { id: 2, active: false },
|
|
2536
|
+
* { id: 3, active: true },
|
|
2537
|
+
* { id: 4, active: false }
|
|
2538
|
+
* ];
|
|
2539
|
+
*
|
|
2540
|
+
* const lastActiveIndex = Arr.findLastIndex(users, user => user.active);
|
|
2541
|
+
* console.log(lastActiveIndex); // 2 - index of last active user
|
|
2542
|
+
*
|
|
2543
|
+
* const lastInactiveIndex = Arr.findLastIndex(users, user => !user.active);
|
|
2544
|
+
* console.log(lastInactiveIndex); // 3 - index of last inactive user
|
|
2545
|
+
*
|
|
2546
|
+
* // Empty array handling
|
|
2547
|
+
* const emptyResult = Arr.findLastIndex([], (x: number) => x > 0); // -1
|
|
2548
|
+
*
|
|
2549
|
+
* // Curried usage for functional composition
|
|
2550
|
+
* const findLastNegativeIndex = Arr.findLastIndex((x: number) => x < 0);
|
|
2551
|
+
* const findLastLongStringIndex = Arr.findLastIndex((s: string) => s.length > 5);
|
|
2552
|
+
*
|
|
2553
|
+
* const datasets = [
|
|
2554
|
+
* [1, 2, -3, 4, -5], // last negative at index 4
|
|
2555
|
+
* [5, 6, 7, 8], // no negative
|
|
2556
|
+
* [-1, 0, 1, -2] // last negative at index 3
|
|
2557
|
+
* ];
|
|
2558
|
+
*
|
|
2559
|
+
* const lastNegativeIndices = datasets.map(findLastNegativeIndex);
|
|
2560
|
+
* // [4, -1, 3]
|
|
2561
|
+
*
|
|
2562
|
+
* // Functional composition
|
|
2563
|
+
* const data = ['short', 'medium', 'very long string', 'tiny', 'another long one'];
|
|
2564
|
+
* const lastLongIndex = Arr.findLastIndex(data, s => s.length > 8);
|
|
2565
|
+
* console.log(lastLongIndex); // 4 - index of 'another long one'
|
|
2566
|
+
*
|
|
2567
|
+
* // Using with pipe
|
|
2568
|
+
* const result = pipe(['a', 'bb', 'ccc', 'bb'])
|
|
2569
|
+
* .map(Arr.findLastIndex((s: string) => s.length === 2))
|
|
2570
|
+
* .value; // 3 (last occurrence of 'bb')
|
|
2571
|
+
*
|
|
2572
|
+
* // Comparing with findIndex
|
|
2573
|
+
* const values = [1, 2, 3, 2, 4];
|
|
2574
|
+
* const firstTwo = Arr.findIndex(values, x => x === 2); // 1
|
|
2575
|
+
* const lastTwo = Arr.findLastIndex(values, x => x === 2); // 3
|
|
2576
|
+
*
|
|
2577
|
+
* // Type safety with tuples
|
|
2578
|
+
* const tuple = [10, 20, 30, 20] as const;
|
|
2579
|
+
* const lastTwentyIndex = Arr.findLastIndex(tuple, x => x === 20);
|
|
2580
|
+
* // Type: ArrayIndex<readonly [10, 20, 30, 20]> | -1
|
|
2581
|
+
* // Value: 3
|
|
2582
|
+
* ```
|
|
2583
|
+
*
|
|
2584
|
+
* @see {@link findLast} for finding the element instead of its index
|
|
2585
|
+
* @see {@link findIndex} for finding the first occurrence
|
|
2586
|
+
* @see {@link lastIndexOf} for finding elements by equality (not predicate)
|
|
2587
|
+
*/
|
|
2588
|
+
export function findLastIndex<Ar extends readonly unknown[]>(
|
|
2589
|
+
array: Ar,
|
|
2590
|
+
predicate: (value: Ar[number], index: ArrayIndex<Ar>, arr: Ar) => boolean,
|
|
2591
|
+
): ArrayIndex<Ar> | -1;
|
|
2592
|
+
|
|
2593
|
+
export function findLastIndex<E>(
|
|
2594
|
+
predicate: (value: E, index: SizeType.Arr, arr: readonly E[]) => boolean,
|
|
2595
|
+
): (array: readonly E[]) => SizeType.Arr | -1;
|
|
2596
|
+
|
|
2597
|
+
export function findLastIndex<E>(
|
|
2598
|
+
...args:
|
|
2599
|
+
| readonly [
|
|
2600
|
+
array: readonly E[],
|
|
2601
|
+
predicate: (
|
|
2602
|
+
value: E,
|
|
2603
|
+
index: SizeType.Arr,
|
|
2604
|
+
arr: readonly E[],
|
|
2605
|
+
) => boolean,
|
|
2606
|
+
]
|
|
2607
|
+
| readonly [
|
|
2608
|
+
predicate: (
|
|
2609
|
+
value: E,
|
|
2610
|
+
index: SizeType.Arr,
|
|
2611
|
+
arr: readonly E[],
|
|
2612
|
+
) => boolean,
|
|
2613
|
+
]
|
|
2614
|
+
): SizeType.Arr | -1 | ((array: readonly E[]) => SizeType.Arr | -1) {
|
|
2615
|
+
switch (args.length) {
|
|
2616
|
+
case 2: {
|
|
2617
|
+
const [array, predicate] = args;
|
|
2618
|
+
return pipe(
|
|
2619
|
+
array.findLastIndex(
|
|
2620
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
2621
|
+
predicate as (value: E, index: number) => boolean,
|
|
2622
|
+
),
|
|
2623
|
+
).map((idx) => (idx >= 0 ? asUint32(idx) : -1)).value;
|
|
2624
|
+
}
|
|
2625
|
+
case 1: {
|
|
2626
|
+
const [predicate] = args;
|
|
2627
|
+
return (array) => findLastIndex(array, predicate);
|
|
2263
2628
|
}
|
|
2264
2629
|
}
|
|
2265
2630
|
}
|
|
@@ -2285,10 +2650,10 @@ export namespace Arr {
|
|
|
2285
2650
|
* console.log(Optional.unwrapOr(result2, -1)); // 1
|
|
2286
2651
|
* ```
|
|
2287
2652
|
*/
|
|
2288
|
-
export function indexOf<
|
|
2289
|
-
array:
|
|
2290
|
-
searchElement:
|
|
2291
|
-
):
|
|
2653
|
+
export function indexOf<Ar extends readonly unknown[]>(
|
|
2654
|
+
array: Ar,
|
|
2655
|
+
searchElement: Ar[number],
|
|
2656
|
+
): ArrayIndex<Ar> | -1;
|
|
2292
2657
|
|
|
2293
2658
|
export function indexOf<E>(
|
|
2294
2659
|
searchElement: E,
|
|
@@ -2308,20 +2673,20 @@ export namespace Arr {
|
|
|
2308
2673
|
}
|
|
2309
2674
|
case 1: {
|
|
2310
2675
|
const [searchElement] = args;
|
|
2311
|
-
return (array
|
|
2676
|
+
return (array) => indexOf(array, searchElement);
|
|
2312
2677
|
}
|
|
2313
2678
|
}
|
|
2314
2679
|
}
|
|
2315
2680
|
|
|
2316
|
-
export function indexOfFrom<
|
|
2317
|
-
array:
|
|
2318
|
-
searchElement:
|
|
2319
|
-
fromIndex:
|
|
2320
|
-
):
|
|
2681
|
+
export function indexOfFrom<Ar extends readonly unknown[]>(
|
|
2682
|
+
array: Ar,
|
|
2683
|
+
searchElement: Ar[number],
|
|
2684
|
+
fromIndex: ArgArrayIndexWithNegative<Ar>,
|
|
2685
|
+
): ArrayIndex<Ar> | -1;
|
|
2321
2686
|
|
|
2322
2687
|
export function indexOfFrom<E>(
|
|
2323
2688
|
searchElement: E,
|
|
2324
|
-
fromIndex: SizeType.
|
|
2689
|
+
fromIndex: SizeType.ArgArrWithNegative,
|
|
2325
2690
|
): (array: readonly E[]) => SizeType.Arr | -1;
|
|
2326
2691
|
|
|
2327
2692
|
export function indexOfFrom<E>(
|
|
@@ -2329,9 +2694,9 @@ export namespace Arr {
|
|
|
2329
2694
|
| readonly [
|
|
2330
2695
|
array: readonly E[],
|
|
2331
2696
|
searchElement: E,
|
|
2332
|
-
fromIndex: SizeType.
|
|
2697
|
+
fromIndex: SizeType.ArgArrWithNegative,
|
|
2333
2698
|
]
|
|
2334
|
-
| readonly [searchElement: E, fromIndex: SizeType.
|
|
2699
|
+
| readonly [searchElement: E, fromIndex: SizeType.ArgArrWithNegative]
|
|
2335
2700
|
): SizeType.Arr | -1 | ((array: readonly E[]) => SizeType.Arr | -1) {
|
|
2336
2701
|
switch (args.length) {
|
|
2337
2702
|
case 3: {
|
|
@@ -2341,8 +2706,7 @@ export namespace Arr {
|
|
|
2341
2706
|
}
|
|
2342
2707
|
case 2: {
|
|
2343
2708
|
const [searchElement, fromIndex] = args;
|
|
2344
|
-
return (array
|
|
2345
|
-
indexOfFrom(array, searchElement, fromIndex);
|
|
2709
|
+
return (array) => indexOfFrom(array, searchElement, fromIndex);
|
|
2346
2710
|
}
|
|
2347
2711
|
}
|
|
2348
2712
|
}
|
|
@@ -2368,10 +2732,10 @@ export namespace Arr {
|
|
|
2368
2732
|
* console.log(Optional.unwrapOr(result2, -1)); // 3
|
|
2369
2733
|
* ```
|
|
2370
2734
|
*/
|
|
2371
|
-
export function lastIndexOf<
|
|
2372
|
-
array:
|
|
2373
|
-
searchElement:
|
|
2374
|
-
):
|
|
2735
|
+
export function lastIndexOf<Ar extends readonly unknown[]>(
|
|
2736
|
+
array: Ar,
|
|
2737
|
+
searchElement: Ar[number],
|
|
2738
|
+
): ArrayIndex<Ar> | -1;
|
|
2375
2739
|
|
|
2376
2740
|
export function lastIndexOf<E>(
|
|
2377
2741
|
searchElement: E,
|
|
@@ -2390,20 +2754,20 @@ export namespace Arr {
|
|
|
2390
2754
|
}
|
|
2391
2755
|
case 1: {
|
|
2392
2756
|
const [searchElement] = args;
|
|
2393
|
-
return (array
|
|
2757
|
+
return (array) => lastIndexOf(array, searchElement);
|
|
2394
2758
|
}
|
|
2395
2759
|
}
|
|
2396
2760
|
}
|
|
2397
2761
|
|
|
2398
|
-
export function lastIndexOfFrom<
|
|
2399
|
-
array:
|
|
2400
|
-
searchElement:
|
|
2401
|
-
fromIndex:
|
|
2402
|
-
):
|
|
2762
|
+
export function lastIndexOfFrom<Ar extends readonly unknown[]>(
|
|
2763
|
+
array: Ar,
|
|
2764
|
+
searchElement: Ar[number],
|
|
2765
|
+
fromIndex: ArgArrayIndexWithNegative<Ar>,
|
|
2766
|
+
): ArrayIndex<Ar> | -1;
|
|
2403
2767
|
|
|
2404
2768
|
export function lastIndexOfFrom<E>(
|
|
2405
2769
|
searchElement: E,
|
|
2406
|
-
fromIndex: SizeType.
|
|
2770
|
+
fromIndex: SizeType.ArgArrWithNegative,
|
|
2407
2771
|
): (array: readonly E[]) => SizeType.Arr | -1;
|
|
2408
2772
|
|
|
2409
2773
|
export function lastIndexOfFrom<E>(
|
|
@@ -2411,9 +2775,9 @@ export namespace Arr {
|
|
|
2411
2775
|
| readonly [
|
|
2412
2776
|
array: readonly E[],
|
|
2413
2777
|
searchElement: E,
|
|
2414
|
-
fromIndex: SizeType.
|
|
2778
|
+
fromIndex: SizeType.ArgArrWithNegative,
|
|
2415
2779
|
]
|
|
2416
|
-
| readonly [searchElement: E, fromIndex: SizeType.
|
|
2780
|
+
| readonly [searchElement: E, fromIndex: SizeType.ArgArrWithNegative]
|
|
2417
2781
|
): SizeType.Arr | -1 | ((array: readonly E[]) => SizeType.Arr | -1) {
|
|
2418
2782
|
switch (args.length) {
|
|
2419
2783
|
case 3: {
|
|
@@ -2425,8 +2789,145 @@ export namespace Arr {
|
|
|
2425
2789
|
}
|
|
2426
2790
|
case 2: {
|
|
2427
2791
|
const [searchElement, fromIndex] = args;
|
|
2428
|
-
return (array
|
|
2429
|
-
|
|
2792
|
+
return (array) => lastIndexOfFrom(array, searchElement, fromIndex);
|
|
2793
|
+
}
|
|
2794
|
+
}
|
|
2795
|
+
}
|
|
2796
|
+
|
|
2797
|
+
/**
|
|
2798
|
+
* Tests whether all elements in an array pass a test implemented by a predicate function.
|
|
2799
|
+
*
|
|
2800
|
+
* This function returns `true` if all elements satisfy the predicate, `false` otherwise.
|
|
2801
|
+
* For empty arrays, it returns `true` (vacuous truth).
|
|
2802
|
+
* Supports type guard predicates for type narrowing of the entire array.
|
|
2803
|
+
*
|
|
2804
|
+
* @template Ar The exact type of the input array.
|
|
2805
|
+
* @template E The type of elements in the array.
|
|
2806
|
+
* @template S The narrowed type when using type guard predicates.
|
|
2807
|
+
* @param array The array to test.
|
|
2808
|
+
* @param predicate A function that tests each element.
|
|
2809
|
+
* @returns `true` if all elements pass the test, `false` otherwise.
|
|
2810
|
+
*
|
|
2811
|
+
* @example
|
|
2812
|
+
* ```typescript
|
|
2813
|
+
* // Direct usage
|
|
2814
|
+
* const numbers = [2, 4, 6, 8];
|
|
2815
|
+
* const allEven = Arr.every(numbers, n => n % 2 === 0); // true
|
|
2816
|
+
*
|
|
2817
|
+
* // Type guard usage - narrows entire array type
|
|
2818
|
+
* const mixed: (string | number)[] = ['hello', 'world'];
|
|
2819
|
+
* if (Arr.every(mixed, (x): x is string => typeof x === 'string')) {
|
|
2820
|
+
* // TypeScript knows mixed is string[] here
|
|
2821
|
+
* console.log(mixed.map(s => s.toUpperCase()));
|
|
2822
|
+
* }
|
|
2823
|
+
*
|
|
2824
|
+
* // Curried usage with type guards
|
|
2825
|
+
* const isString = (x: unknown): x is string => typeof x === 'string';
|
|
2826
|
+
* const allStrings = Arr.every(isString);
|
|
2827
|
+
* const data: unknown[] = ['a', 'b', 'c'];
|
|
2828
|
+
* if (allStrings(data)) {
|
|
2829
|
+
* // TypeScript knows data is string[] here
|
|
2830
|
+
* console.log(data.join(''));
|
|
2831
|
+
* }
|
|
2832
|
+
*
|
|
2833
|
+
* // Empty array
|
|
2834
|
+
* const empty: number[] = [];
|
|
2835
|
+
* const result2 = Arr.every(empty, n => n > 0); // true
|
|
2836
|
+
* ```
|
|
2837
|
+
*/
|
|
2838
|
+
// Type guard overloads - narrow the entire array type
|
|
2839
|
+
export function every<E, S extends E>(
|
|
2840
|
+
array: readonly E[],
|
|
2841
|
+
predicate: (a: E, index: SizeType.Arr) => a is S,
|
|
2842
|
+
): array is readonly S[];
|
|
2843
|
+
|
|
2844
|
+
export function every<E, S extends E>(
|
|
2845
|
+
predicate: (a: E, index: SizeType.Arr) => a is S,
|
|
2846
|
+
): (array: readonly E[]) => array is readonly S[];
|
|
2847
|
+
|
|
2848
|
+
// Regular boolean predicate overloads
|
|
2849
|
+
export function every<Ar extends readonly unknown[]>(
|
|
2850
|
+
array: Ar,
|
|
2851
|
+
predicate: (a: Ar[number], index: ArrayIndex<Ar>) => boolean,
|
|
2852
|
+
): boolean;
|
|
2853
|
+
|
|
2854
|
+
export function every<E>(
|
|
2855
|
+
predicate: (a: E, index: SizeType.Arr) => boolean,
|
|
2856
|
+
): (array: readonly E[]) => boolean;
|
|
2857
|
+
|
|
2858
|
+
export function every<E>(
|
|
2859
|
+
...args:
|
|
2860
|
+
| readonly [
|
|
2861
|
+
array: readonly E[],
|
|
2862
|
+
predicate: (a: E, index: SizeType.Arr) => boolean,
|
|
2863
|
+
]
|
|
2864
|
+
| readonly [predicate: (a: E, index: SizeType.Arr) => boolean]
|
|
2865
|
+
): boolean | ((array: readonly E[]) => boolean) {
|
|
2866
|
+
switch (args.length) {
|
|
2867
|
+
case 2: {
|
|
2868
|
+
const [array, predicate] = args;
|
|
2869
|
+
return array.every((a, i) => predicate(a, asUint32(i)));
|
|
2870
|
+
}
|
|
2871
|
+
case 1: {
|
|
2872
|
+
const [predicate] = args;
|
|
2873
|
+
return (array) => every(array, predicate);
|
|
2874
|
+
}
|
|
2875
|
+
}
|
|
2876
|
+
}
|
|
2877
|
+
|
|
2878
|
+
/**
|
|
2879
|
+
* Tests whether at least one element in an array passes a test implemented by a predicate function.
|
|
2880
|
+
*
|
|
2881
|
+
* This function returns `true` if at least one element satisfies the predicate, `false` otherwise.
|
|
2882
|
+
* For empty arrays, it returns `false`.
|
|
2883
|
+
*
|
|
2884
|
+
* @template Ar The exact type of the input array.
|
|
2885
|
+
* @template E The type of elements in the array.
|
|
2886
|
+
* @param array The array to test.
|
|
2887
|
+
* @param predicate A function that tests each element.
|
|
2888
|
+
* @returns `true` if at least one element passes the test, `false` otherwise.
|
|
2889
|
+
*
|
|
2890
|
+
* @example
|
|
2891
|
+
* ```typescript
|
|
2892
|
+
* // Direct usage
|
|
2893
|
+
* const numbers = [1, 3, 5, 8];
|
|
2894
|
+
* const hasEven = Arr.some(numbers, n => n % 2 === 0); // true
|
|
2895
|
+
*
|
|
2896
|
+
* // Curried usage
|
|
2897
|
+
* const isNegative = (n: number) => n < 0;
|
|
2898
|
+
* const hasNegative = Arr.some(isNegative);
|
|
2899
|
+
* const result = hasNegative([1, 2, -3]); // true
|
|
2900
|
+
*
|
|
2901
|
+
* // Empty array
|
|
2902
|
+
* const empty: number[] = [];
|
|
2903
|
+
* const result2 = Arr.some(empty, n => n > 0); // false
|
|
2904
|
+
* ```
|
|
2905
|
+
*/
|
|
2906
|
+
export function some<Ar extends readonly unknown[]>(
|
|
2907
|
+
array: Ar,
|
|
2908
|
+
predicate: (a: Ar[number], index: ArrayIndex<Ar>) => boolean,
|
|
2909
|
+
): boolean;
|
|
2910
|
+
|
|
2911
|
+
export function some<E>(
|
|
2912
|
+
predicate: (a: E, index: SizeType.Arr) => boolean,
|
|
2913
|
+
): (array: readonly E[]) => boolean;
|
|
2914
|
+
|
|
2915
|
+
export function some<E>(
|
|
2916
|
+
...args:
|
|
2917
|
+
| readonly [
|
|
2918
|
+
array: readonly E[],
|
|
2919
|
+
predicate: (a: E, index: SizeType.Arr) => boolean,
|
|
2920
|
+
]
|
|
2921
|
+
| readonly [predicate: (a: E, index: SizeType.Arr) => boolean]
|
|
2922
|
+
): boolean | ((array: readonly E[]) => boolean) {
|
|
2923
|
+
switch (args.length) {
|
|
2924
|
+
case 2: {
|
|
2925
|
+
const [array, predicate] = args;
|
|
2926
|
+
return array.some((a, i) => predicate(a, asUint32(i)));
|
|
2927
|
+
}
|
|
2928
|
+
case 1: {
|
|
2929
|
+
const [predicate] = args;
|
|
2930
|
+
return (array) => some(array, predicate);
|
|
2430
2931
|
}
|
|
2431
2932
|
}
|
|
2432
2933
|
}
|
|
@@ -2448,12 +2949,12 @@ export namespace Arr {
|
|
|
2448
2949
|
* Arr.foldl(['a', 'b', 'c'], (acc, str) => acc + str.toUpperCase(), ''); // 'ABC'
|
|
2449
2950
|
* ```
|
|
2450
2951
|
*/
|
|
2451
|
-
export function foldl<
|
|
2452
|
-
array:
|
|
2952
|
+
export function foldl<Ar extends readonly unknown[], P>(
|
|
2953
|
+
array: Ar,
|
|
2453
2954
|
callbackfn: (
|
|
2454
2955
|
previousValue: P,
|
|
2455
|
-
currentValue:
|
|
2456
|
-
currentIndex:
|
|
2956
|
+
currentValue: Ar[number],
|
|
2957
|
+
currentIndex: ArrayIndex<Ar>,
|
|
2457
2958
|
) => P,
|
|
2458
2959
|
initialValue: P,
|
|
2459
2960
|
): P;
|
|
@@ -2497,7 +2998,7 @@ export namespace Arr {
|
|
|
2497
2998
|
}
|
|
2498
2999
|
case 2: {
|
|
2499
3000
|
const [callbackfn, initialValue] = args;
|
|
2500
|
-
return (array
|
|
3001
|
+
return (array) => foldl(array, callbackfn, initialValue);
|
|
2501
3002
|
}
|
|
2502
3003
|
}
|
|
2503
3004
|
}
|
|
@@ -2522,12 +3023,12 @@ export namespace Arr {
|
|
|
2522
3023
|
* console.log(result); // "abc"
|
|
2523
3024
|
* ```
|
|
2524
3025
|
*/
|
|
2525
|
-
export function foldr<
|
|
2526
|
-
array:
|
|
3026
|
+
export function foldr<Ar extends readonly unknown[], P>(
|
|
3027
|
+
array: Ar,
|
|
2527
3028
|
callbackfn: (
|
|
2528
3029
|
previousValue: P,
|
|
2529
|
-
currentValue:
|
|
2530
|
-
currentIndex:
|
|
3030
|
+
currentValue: Ar[number],
|
|
3031
|
+
currentIndex: ArrayIndex<Ar>,
|
|
2531
3032
|
) => P,
|
|
2532
3033
|
initialValue: P,
|
|
2533
3034
|
): P;
|
|
@@ -2571,7 +3072,7 @@ export namespace Arr {
|
|
|
2571
3072
|
}
|
|
2572
3073
|
case 2: {
|
|
2573
3074
|
const [callbackfn, initialValue] = args;
|
|
2574
|
-
return (array
|
|
3075
|
+
return (array) => foldr(array, callbackfn, initialValue);
|
|
2575
3076
|
}
|
|
2576
3077
|
}
|
|
2577
3078
|
}
|
|
@@ -2589,25 +3090,20 @@ export namespace Arr {
|
|
|
2589
3090
|
* Arr.min([]); // Optional.none
|
|
2590
3091
|
* ```
|
|
2591
3092
|
*/
|
|
2592
|
-
export function min<
|
|
2593
|
-
array:
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
comparator?: (x: E, y: E) => number,
|
|
2600
|
-
): Optional<E>;
|
|
2601
|
-
|
|
2602
|
-
export function min<E>(
|
|
2603
|
-
array: NonEmptyArray<E>,
|
|
2604
|
-
comparator: (x: E, y: E) => number,
|
|
2605
|
-
): Optional.Some<E>;
|
|
3093
|
+
export function min<Ar extends readonly number[]>(
|
|
3094
|
+
array: Ar,
|
|
3095
|
+
// If the array elements are numbers, comparator is optional.
|
|
3096
|
+
comparator?: (x: Ar[number], y: Ar[number]) => number,
|
|
3097
|
+
): Ar extends NonEmptyArray<unknown>
|
|
3098
|
+
? Optional.Some<Ar[number]>
|
|
3099
|
+
: Optional<Ar[number]>;
|
|
2606
3100
|
|
|
2607
|
-
export function min<
|
|
2608
|
-
array:
|
|
2609
|
-
comparator: (x:
|
|
2610
|
-
):
|
|
3101
|
+
export function min<Ar extends readonly unknown[]>(
|
|
3102
|
+
array: Ar,
|
|
3103
|
+
comparator: (x: Ar[number], y: Ar[number]) => number,
|
|
3104
|
+
): Ar extends NonEmptyArray<unknown>
|
|
3105
|
+
? Optional.Some<Ar[number]>
|
|
3106
|
+
: Optional<Ar[number]>;
|
|
2611
3107
|
|
|
2612
3108
|
export function min<E extends number>(
|
|
2613
3109
|
array: readonly E[],
|
|
@@ -2645,25 +3141,20 @@ export namespace Arr {
|
|
|
2645
3141
|
* Arr.max([]); // Optional.none
|
|
2646
3142
|
* ```
|
|
2647
3143
|
*/
|
|
2648
|
-
export function max<
|
|
2649
|
-
array:
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
comparator?: (x: E, y: E) => number,
|
|
2656
|
-
): Optional<E>;
|
|
2657
|
-
|
|
2658
|
-
export function max<E>(
|
|
2659
|
-
array: NonEmptyArray<E>,
|
|
2660
|
-
comparator: (x: E, y: E) => number,
|
|
2661
|
-
): Optional.Some<E>;
|
|
3144
|
+
export function max<Ar extends readonly number[]>(
|
|
3145
|
+
array: Ar,
|
|
3146
|
+
// If the array elements are numbers, comparator is optional.
|
|
3147
|
+
comparator?: (x: Ar[number], y: Ar[number]) => number,
|
|
3148
|
+
): Ar extends NonEmptyArray<unknown>
|
|
3149
|
+
? Optional.Some<Ar[number]>
|
|
3150
|
+
: Optional<Ar[number]>;
|
|
2662
3151
|
|
|
2663
|
-
export function max<
|
|
2664
|
-
array:
|
|
2665
|
-
comparator: (x:
|
|
2666
|
-
):
|
|
3152
|
+
export function max<Ar extends readonly unknown[]>(
|
|
3153
|
+
array: Ar,
|
|
3154
|
+
comparator: (x: Ar[number], y: Ar[number]) => number,
|
|
3155
|
+
): Ar extends NonEmptyArray<unknown>
|
|
3156
|
+
? Optional.Some<Ar[number]>
|
|
3157
|
+
: Optional<Ar[number]>;
|
|
2667
3158
|
|
|
2668
3159
|
export function max<E extends number>(
|
|
2669
3160
|
array: readonly E[],
|
|
@@ -2694,27 +3185,21 @@ export namespace Arr {
|
|
|
2694
3185
|
* Arr.minBy([], p => p.age); // Optional.none
|
|
2695
3186
|
* ```
|
|
2696
3187
|
*/
|
|
2697
|
-
export function minBy<
|
|
2698
|
-
array:
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
comparatorValueMapper: (value: E) => number,
|
|
2705
|
-
): Optional<E>;
|
|
2706
|
-
|
|
2707
|
-
export function minBy<E, V>(
|
|
2708
|
-
array: NonEmptyArray<E>,
|
|
2709
|
-
comparatorValueMapper: (value: E) => V,
|
|
2710
|
-
comparator: (x: V, y: V) => number,
|
|
2711
|
-
): Optional.Some<E>;
|
|
3188
|
+
export function minBy<Ar extends readonly unknown[]>(
|
|
3189
|
+
array: Ar,
|
|
3190
|
+
// If the array elements are mapped to numbers, comparator is optional.
|
|
3191
|
+
comparatorValueMapper: (value: Ar[number]) => number,
|
|
3192
|
+
): Ar extends NonEmptyArray<unknown>
|
|
3193
|
+
? Optional.Some<Ar[number]>
|
|
3194
|
+
: Optional<Ar[number]>;
|
|
2712
3195
|
|
|
2713
|
-
export function minBy<
|
|
2714
|
-
array:
|
|
2715
|
-
comparatorValueMapper: (value:
|
|
3196
|
+
export function minBy<Ar extends readonly unknown[], V>(
|
|
3197
|
+
array: Ar,
|
|
3198
|
+
comparatorValueMapper: (value: Ar[number]) => V,
|
|
2716
3199
|
comparator: (x: V, y: V) => number,
|
|
2717
|
-
):
|
|
3200
|
+
): Ar extends NonEmptyArray<unknown>
|
|
3201
|
+
? Optional.Some<Ar[number]>
|
|
3202
|
+
: Optional<Ar[number]>;
|
|
2718
3203
|
|
|
2719
3204
|
export function minBy<E, V>(
|
|
2720
3205
|
array: readonly E[],
|
|
@@ -2749,27 +3234,21 @@ export namespace Arr {
|
|
|
2749
3234
|
* Arr.maxBy([], p => p.age); // Optional.none
|
|
2750
3235
|
* ```
|
|
2751
3236
|
*/
|
|
2752
|
-
export function maxBy<
|
|
2753
|
-
array:
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
comparatorValueMapper: (value: E) => number,
|
|
2760
|
-
): Optional<E>;
|
|
2761
|
-
|
|
2762
|
-
export function maxBy<E, V>(
|
|
2763
|
-
array: NonEmptyArray<E>,
|
|
2764
|
-
comparatorValueMapper: (value: E) => V,
|
|
2765
|
-
comparator: (x: V, y: V) => number,
|
|
2766
|
-
): Optional.Some<E>;
|
|
3237
|
+
export function maxBy<Ar extends readonly unknown[]>(
|
|
3238
|
+
array: Ar,
|
|
3239
|
+
// If the array elements are mapped to numbers, comparator is optional.
|
|
3240
|
+
comparatorValueMapper: (value: Ar[number]) => number,
|
|
3241
|
+
): Ar extends NonEmptyArray<unknown>
|
|
3242
|
+
? Optional.Some<Ar[number]>
|
|
3243
|
+
: Optional<Ar[number]>;
|
|
2767
3244
|
|
|
2768
|
-
export function maxBy<
|
|
2769
|
-
array:
|
|
2770
|
-
comparatorValueMapper: (value:
|
|
3245
|
+
export function maxBy<Ar extends readonly unknown[], V>(
|
|
3246
|
+
array: Ar,
|
|
3247
|
+
comparatorValueMapper: (value: Ar[number]) => V,
|
|
2771
3248
|
comparator: (x: V, y: V) => number,
|
|
2772
|
-
):
|
|
3249
|
+
): Ar extends NonEmptyArray<unknown>
|
|
3250
|
+
? Optional.Some<Ar[number]>
|
|
3251
|
+
: Optional<Ar[number]>;
|
|
2773
3252
|
|
|
2774
3253
|
export function maxBy<E, V>(
|
|
2775
3254
|
array: readonly E[],
|
|
@@ -2801,9 +3280,9 @@ export namespace Arr {
|
|
|
2801
3280
|
* console.log(result); // 3
|
|
2802
3281
|
* ```
|
|
2803
3282
|
*/
|
|
2804
|
-
export function count<
|
|
2805
|
-
array:
|
|
2806
|
-
predicate: (value:
|
|
3283
|
+
export function count<Ar extends readonly unknown[]>(
|
|
3284
|
+
array: Ar,
|
|
3285
|
+
predicate: (value: Ar[number], index: ArrayIndex<Ar>) => boolean,
|
|
2807
3286
|
): SizeType.Arr;
|
|
2808
3287
|
|
|
2809
3288
|
export function count<E>(
|
|
@@ -2829,7 +3308,7 @@ export namespace Arr {
|
|
|
2829
3308
|
}
|
|
2830
3309
|
case 1: {
|
|
2831
3310
|
const [predicate] = args;
|
|
2832
|
-
return (array
|
|
3311
|
+
return (array) => count(array, predicate);
|
|
2833
3312
|
}
|
|
2834
3313
|
}
|
|
2835
3314
|
}
|
|
@@ -2854,10 +3333,13 @@ export namespace Arr {
|
|
|
2854
3333
|
* // IMap { 'a' => 2, 'b' => 1 }
|
|
2855
3334
|
* ```
|
|
2856
3335
|
*/
|
|
2857
|
-
export function countBy<
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
3336
|
+
export function countBy<
|
|
3337
|
+
Ar extends readonly unknown[],
|
|
3338
|
+
G extends MapSetKeyType,
|
|
3339
|
+
>(
|
|
3340
|
+
array: Ar,
|
|
3341
|
+
grouper: (value: Ar[number], index: ArrayIndex<Ar>) => G,
|
|
3342
|
+
): IMap<G, ArrayIndex<Ar>>;
|
|
2861
3343
|
|
|
2862
3344
|
export function countBy<E, G extends MapSetKeyType>(
|
|
2863
3345
|
grouper: (value: E, index: SizeType.Arr) => G,
|
|
@@ -2887,7 +3369,7 @@ export namespace Arr {
|
|
|
2887
3369
|
}
|
|
2888
3370
|
case 1: {
|
|
2889
3371
|
const [grouper] = args;
|
|
2890
|
-
return (array
|
|
3372
|
+
return (array) => countBy(array, grouper);
|
|
2891
3373
|
}
|
|
2892
3374
|
}
|
|
2893
3375
|
}
|
|
@@ -2953,12 +3435,12 @@ export namespace Arr {
|
|
|
2953
3435
|
): Result<string, Error> | ((array: readonly E[]) => Result<string, Error>) {
|
|
2954
3436
|
switch (args.length) {
|
|
2955
3437
|
case 0:
|
|
2956
|
-
return (array
|
|
3438
|
+
return (array) => joinImpl(array, undefined);
|
|
2957
3439
|
|
|
2958
3440
|
case 1: {
|
|
2959
3441
|
const [arg] = args;
|
|
2960
3442
|
if (isString(arg) || isUndefined(arg)) {
|
|
2961
|
-
return (array
|
|
3443
|
+
return (array) => joinImpl(array, arg);
|
|
2962
3444
|
}
|
|
2963
3445
|
return joinImpl(arg, undefined);
|
|
2964
3446
|
}
|
|
@@ -3019,6 +3501,145 @@ export namespace Arr {
|
|
|
3019
3501
|
tp(array1[i]!, array2[i]!),
|
|
3020
3502
|
) as unknown as List.Zip<Ar1, Ar2>;
|
|
3021
3503
|
|
|
3504
|
+
/**
|
|
3505
|
+
* Creates a new tuple by transforming each element with a mapping function.
|
|
3506
|
+
*
|
|
3507
|
+
* Preserves the tuple's length while allowing element type transformation.
|
|
3508
|
+
* The resulting tuple has the same structure but with transformed element types.
|
|
3509
|
+
*
|
|
3510
|
+
* @template T - The type of the input tuple
|
|
3511
|
+
* @template B - The type that elements will be transformed to
|
|
3512
|
+
* @param array - The input tuple
|
|
3513
|
+
* @param mapFn - Function that transforms each element (receives element and index)
|
|
3514
|
+
* @returns A new tuple with transformed elements, preserving the original length
|
|
3515
|
+
*
|
|
3516
|
+
* @example
|
|
3517
|
+
* ```typescript
|
|
3518
|
+
* // Basic transformation
|
|
3519
|
+
* const nums = [1, 2, 3] as const;
|
|
3520
|
+
* const doubled = Arr.map(nums, (x) => x * 2); // readonly [2, 4, 6]
|
|
3521
|
+
* const strings = Arr.map(nums, (x) => String(x)); // readonly ['1', '2', '3']
|
|
3522
|
+
*
|
|
3523
|
+
* // With index
|
|
3524
|
+
* const indexed = Arr.map(nums, (x, i) => `${i}:${x}`);
|
|
3525
|
+
* // readonly ['0:1', '1:2', '2:3']
|
|
3526
|
+
*
|
|
3527
|
+
* // Mixed type tuples
|
|
3528
|
+
* const mixed = [1, 'hello', true] as const;
|
|
3529
|
+
* const descriptions = Arr.map(mixed, (x) => `Value: ${x}`);
|
|
3530
|
+
* // readonly ['Value: 1', 'Value: hello', 'Value: true']
|
|
3531
|
+
* ```
|
|
3532
|
+
*/
|
|
3533
|
+
export function map<const Ar extends readonly unknown[], B>(
|
|
3534
|
+
array: Ar,
|
|
3535
|
+
mapFn: (a: Ar[number], index: ArrayIndex<Ar>) => B,
|
|
3536
|
+
): Readonly<{ [K in keyof Ar]: B }>;
|
|
3537
|
+
|
|
3538
|
+
// curried version
|
|
3539
|
+
export function map<A, B>(
|
|
3540
|
+
mapFn: (a: A, index: SizeType.Arr) => B,
|
|
3541
|
+
): <Ar extends readonly A[]>(array: Ar) => Readonly<{ [K in keyof Ar]: B }>;
|
|
3542
|
+
|
|
3543
|
+
export function map<A, B>(
|
|
3544
|
+
...args:
|
|
3545
|
+
| readonly [array: readonly A[], mapFn: (a: A, index: SizeType.Arr) => B]
|
|
3546
|
+
| readonly [mapFn: (a: A, index: SizeType.Arr) => B]
|
|
3547
|
+
): readonly B[] | ((array: readonly A[]) => readonly B[]) {
|
|
3548
|
+
switch (args.length) {
|
|
3549
|
+
case 2: {
|
|
3550
|
+
const [array, mapFn] = args;
|
|
3551
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
3552
|
+
return array.map(mapFn as never);
|
|
3553
|
+
}
|
|
3554
|
+
case 1: {
|
|
3555
|
+
const [mapFn] = args;
|
|
3556
|
+
return (array: readonly A[]) => map(array, mapFn);
|
|
3557
|
+
}
|
|
3558
|
+
}
|
|
3559
|
+
}
|
|
3560
|
+
|
|
3561
|
+
/**
|
|
3562
|
+
* Filters an array based on a predicate function.
|
|
3563
|
+
*
|
|
3564
|
+
* This function returns a new array containing only the elements that satisfy the predicate.
|
|
3565
|
+
* It provides both direct usage and curried versions for functional composition.
|
|
3566
|
+
* Supports type guard predicates for type narrowing.
|
|
3567
|
+
*
|
|
3568
|
+
* @template Ar The exact type of the input array, used for precise return type inference.
|
|
3569
|
+
* @template E The type of elements in the array.
|
|
3570
|
+
* @template S The narrowed type when using type guard predicates.
|
|
3571
|
+
* @param array The array to filter.
|
|
3572
|
+
* @param predicate A function that tests each element. Returns `true` to keep the element, `false` to filter it out.
|
|
3573
|
+
* @returns A new array containing only the elements that satisfy the predicate.
|
|
3574
|
+
*
|
|
3575
|
+
* @example
|
|
3576
|
+
* ```typescript
|
|
3577
|
+
* // Direct usage
|
|
3578
|
+
* const numbers = [1, 2, 3, 4, 5];
|
|
3579
|
+
* const evens = Arr.filter(numbers, n => n % 2 === 0); // [2, 4]
|
|
3580
|
+
*
|
|
3581
|
+
* // Type guard usage
|
|
3582
|
+
* const mixed: (string | number | null)[] = ['hello', 42, null, 'world'];
|
|
3583
|
+
* const strings = Arr.filter(mixed, (x): x is string => typeof x === 'string'); // string[]
|
|
3584
|
+
* const notNull = Arr.filter(mixed, (x): x is NonNullable<typeof x> => x != null); // (string | number)[]
|
|
3585
|
+
*
|
|
3586
|
+
* // Curried usage with type guards
|
|
3587
|
+
* const isString = (x: unknown): x is string => typeof x === 'string';
|
|
3588
|
+
* const filterStrings = Arr.filter(isString);
|
|
3589
|
+
* const result = filterStrings(['a', 1, 'b', 2]); // string[]
|
|
3590
|
+
*
|
|
3591
|
+
* // Functional composition
|
|
3592
|
+
* const processNumbers = pipe(
|
|
3593
|
+
* Arr.filter((n: number) => n > 0),
|
|
3594
|
+
* Arr.map(n => n * 2)
|
|
3595
|
+
* );
|
|
3596
|
+
* ```
|
|
3597
|
+
*
|
|
3598
|
+
* @see {@link filterNot} for filtering with negated predicate
|
|
3599
|
+
* @see {@link every} for testing if all elements satisfy a predicate
|
|
3600
|
+
* @see {@link some} for testing if any elements satisfy a predicate
|
|
3601
|
+
* @see {@link find} for finding the first element that satisfies a predicate
|
|
3602
|
+
*/
|
|
3603
|
+
// Type guard overloads
|
|
3604
|
+
export function filter<Ar extends readonly unknown[], S extends Ar[number]>(
|
|
3605
|
+
array: Ar,
|
|
3606
|
+
predicate: (a: Ar[number], index: ArrayIndex<Ar>) => a is S,
|
|
3607
|
+
): readonly S[];
|
|
3608
|
+
|
|
3609
|
+
export function filter<E, S extends E>(
|
|
3610
|
+
predicate: (a: E, index: SizeType.Arr) => a is S,
|
|
3611
|
+
): (array: readonly E[]) => readonly S[];
|
|
3612
|
+
|
|
3613
|
+
// Regular boolean predicate overloads
|
|
3614
|
+
export function filter<Ar extends readonly unknown[]>(
|
|
3615
|
+
array: Ar,
|
|
3616
|
+
predicate: (a: Ar[number], index: ArrayIndex<Ar>) => boolean,
|
|
3617
|
+
): readonly Ar[number][];
|
|
3618
|
+
|
|
3619
|
+
export function filter<E>(
|
|
3620
|
+
predicate: (a: E, index: SizeType.Arr) => boolean,
|
|
3621
|
+
): (array: readonly E[]) => readonly E[];
|
|
3622
|
+
|
|
3623
|
+
export function filter<E>(
|
|
3624
|
+
...args:
|
|
3625
|
+
| readonly [
|
|
3626
|
+
array: readonly E[],
|
|
3627
|
+
predicate: (a: E, index: SizeType.Arr) => boolean,
|
|
3628
|
+
]
|
|
3629
|
+
| readonly [predicate: (a: E, index: SizeType.Arr) => boolean]
|
|
3630
|
+
): readonly E[] | ((array: readonly E[]) => readonly E[]) {
|
|
3631
|
+
switch (args.length) {
|
|
3632
|
+
case 2: {
|
|
3633
|
+
const [array, predicate] = args;
|
|
3634
|
+
return array.filter((a, i) => predicate(a, asUint32(i)));
|
|
3635
|
+
}
|
|
3636
|
+
case 1: {
|
|
3637
|
+
const [predicate] = args;
|
|
3638
|
+
return (array) => filter(array, predicate);
|
|
3639
|
+
}
|
|
3640
|
+
}
|
|
3641
|
+
}
|
|
3642
|
+
|
|
3022
3643
|
/**
|
|
3023
3644
|
* Filters an array by excluding elements for which the predicate returns true.
|
|
3024
3645
|
* This is the opposite of `Array.prototype.filter`.
|
|
@@ -3037,10 +3658,10 @@ export namespace Arr {
|
|
|
3037
3658
|
* console.log(result); // [1, 3, 5]
|
|
3038
3659
|
* ```
|
|
3039
3660
|
*/
|
|
3040
|
-
export function filterNot<
|
|
3041
|
-
array:
|
|
3042
|
-
predicate: (a:
|
|
3043
|
-
): readonly
|
|
3661
|
+
export function filterNot<Ar extends readonly unknown[]>(
|
|
3662
|
+
array: Ar,
|
|
3663
|
+
predicate: (a: Ar[number], index: ArrayIndex<Ar>) => boolean,
|
|
3664
|
+
): readonly Ar[number][];
|
|
3044
3665
|
|
|
3045
3666
|
export function filterNot<E>(
|
|
3046
3667
|
predicate: (a: E, index: SizeType.Arr) => boolean,
|
|
@@ -3061,7 +3682,127 @@ export namespace Arr {
|
|
|
3061
3682
|
}
|
|
3062
3683
|
case 1: {
|
|
3063
3684
|
const [predicate] = args;
|
|
3064
|
-
return (array
|
|
3685
|
+
return (array) => filterNot(array, predicate);
|
|
3686
|
+
}
|
|
3687
|
+
}
|
|
3688
|
+
}
|
|
3689
|
+
|
|
3690
|
+
/**
|
|
3691
|
+
* Creates a new array with all sub-array elements concatenated into it recursively up to the specified depth.
|
|
3692
|
+
*
|
|
3693
|
+
* This function flattens nested arrays to the specified depth level.
|
|
3694
|
+
* A depth of 1 flattens one level, Number.POSITIVE_INFINITY flattens all levels.
|
|
3695
|
+
*
|
|
3696
|
+
* @template Ar The exact type of the input array.
|
|
3697
|
+
* @template D The depth of flattening.
|
|
3698
|
+
* @param array The array to flatten.
|
|
3699
|
+
* @param depth The depth level specifying how deep a nested array structure should be flattened.
|
|
3700
|
+
* @returns A new array with the sub-array elements concatenated.
|
|
3701
|
+
*
|
|
3702
|
+
* @example
|
|
3703
|
+
* ```typescript
|
|
3704
|
+
* // Direct usage
|
|
3705
|
+
* const nested = [1, [2, [3, 4]], 5];
|
|
3706
|
+
* const flat1 = Arr.flat(nested, 1); // [1, 2, [3, 4], 5]
|
|
3707
|
+
* const flat2 = Arr.flat(nested, 2); // [1, 2, 3, 4, 5]
|
|
3708
|
+
*
|
|
3709
|
+
* // Curried usage
|
|
3710
|
+
* const flattenOnceLevel = Arr.flat(1);
|
|
3711
|
+
* const result = flattenOnceLevel([[1, 2], [3, 4]]); // [1, 2, 3, 4]
|
|
3712
|
+
*
|
|
3713
|
+
* // Flatten all levels
|
|
3714
|
+
* const deepNested = [1, [2, [3, [4, 5]]]];
|
|
3715
|
+
* const allFlat = Arr.flat(deepNested, SafeUint.MAX_VALUE); // [1, 2, 3, 4, 5]
|
|
3716
|
+
* ```
|
|
3717
|
+
*/
|
|
3718
|
+
export function flat<
|
|
3719
|
+
Ar extends readonly unknown[],
|
|
3720
|
+
D extends SafeUintWithSmallInt = 1,
|
|
3721
|
+
>(array: Ar, depth?: D): readonly FlatArray<Ar, D>[];
|
|
3722
|
+
|
|
3723
|
+
export function flat<D extends SafeUintWithSmallInt = 1>(
|
|
3724
|
+
depth?: number,
|
|
3725
|
+
): <Ar extends readonly unknown[]>(array: Ar) => readonly FlatArray<Ar, D>[];
|
|
3726
|
+
|
|
3727
|
+
export function flat<E, D extends SafeUintWithSmallInt = 1>(
|
|
3728
|
+
...args: readonly [array: readonly E[], depth?: D] | readonly [depth?: D]
|
|
3729
|
+
): readonly unknown[] | ((array: readonly unknown[]) => readonly unknown[]) {
|
|
3730
|
+
switch (args.length) {
|
|
3731
|
+
case 2: {
|
|
3732
|
+
const [array, depth] = args;
|
|
3733
|
+
return array.flat(depth);
|
|
3734
|
+
}
|
|
3735
|
+
case 1: {
|
|
3736
|
+
const [arrayOrDepth] = args;
|
|
3737
|
+
if (typeof arrayOrDepth === 'number') {
|
|
3738
|
+
const depth = arrayOrDepth as SafeUintWithSmallInt | undefined;
|
|
3739
|
+
return (array) => flat(array, depth);
|
|
3740
|
+
} else if (arrayOrDepth === undefined) {
|
|
3741
|
+
return (array) => flat(array, 1);
|
|
3742
|
+
} else {
|
|
3743
|
+
expectType<typeof arrayOrDepth, readonly E[]>('=');
|
|
3744
|
+
return arrayOrDepth.flat(1);
|
|
3745
|
+
}
|
|
3746
|
+
}
|
|
3747
|
+
|
|
3748
|
+
case 0:
|
|
3749
|
+
return (array) => flat(array, 1);
|
|
3750
|
+
}
|
|
3751
|
+
}
|
|
3752
|
+
|
|
3753
|
+
/**
|
|
3754
|
+
* Creates a new array with all sub-array elements concatenated into it recursively up to the specified depth,
|
|
3755
|
+
* after first mapping each element using a mapping function.
|
|
3756
|
+
*
|
|
3757
|
+
* This function is equivalent to calling `map` followed by `flat` with depth 1.
|
|
3758
|
+
*
|
|
3759
|
+
* @template Ar The exact type of the input array.
|
|
3760
|
+
* @template E The type of elements in the array.
|
|
3761
|
+
* @template B The type of elements returned by the mapping function.
|
|
3762
|
+
* @param array The array to map and flatten.
|
|
3763
|
+
* @param mapFn A function that produces new elements for the new array.
|
|
3764
|
+
* @returns A new array with mapped elements flattened.
|
|
3765
|
+
*
|
|
3766
|
+
* @example
|
|
3767
|
+
* ```typescript
|
|
3768
|
+
* // Direct usage
|
|
3769
|
+
* const words = ['hello', 'world'];
|
|
3770
|
+
* const chars = Arr.flatMap(words, word => word.split('')); // ['h','e','l','l','o','w','o','r','l','d']
|
|
3771
|
+
*
|
|
3772
|
+
* // Curried usage
|
|
3773
|
+
* const splitWords = Arr.flatMap((word: string) => word.split(''));
|
|
3774
|
+
* const result = splitWords(['foo', 'bar']); // ['f','o','o','b','a','r']
|
|
3775
|
+
*
|
|
3776
|
+
* // With numbers
|
|
3777
|
+
* const numbers = [1, 2, 3];
|
|
3778
|
+
* const doubled = Arr.flatMap(numbers, n => [n, n * 2]); // [1, 2, 2, 4, 3, 6]
|
|
3779
|
+
* ```
|
|
3780
|
+
*/
|
|
3781
|
+
export function flatMap<const Ar extends readonly unknown[], B>(
|
|
3782
|
+
array: Ar,
|
|
3783
|
+
mapFn: (a: Ar[number], index: ArrayIndex<Ar>) => readonly B[],
|
|
3784
|
+
): readonly B[];
|
|
3785
|
+
|
|
3786
|
+
export function flatMap<A, B>(
|
|
3787
|
+
mapFn: (a: A, index: SizeType.Arr) => readonly B[],
|
|
3788
|
+
): (array: readonly A[]) => readonly B[];
|
|
3789
|
+
|
|
3790
|
+
export function flatMap<A, B>(
|
|
3791
|
+
...args:
|
|
3792
|
+
| readonly [
|
|
3793
|
+
array: readonly A[],
|
|
3794
|
+
mapFn: (a: A, index: SizeType.Arr) => readonly B[],
|
|
3795
|
+
]
|
|
3796
|
+
| readonly [mapFn: (a: A, index: SizeType.Arr) => readonly B[]]
|
|
3797
|
+
): readonly B[] | ((array: readonly A[]) => readonly B[]) {
|
|
3798
|
+
switch (args.length) {
|
|
3799
|
+
case 2: {
|
|
3800
|
+
const [array, mapFn] = args;
|
|
3801
|
+
return array.flatMap((a, i) => mapFn(a, asUint32(i)));
|
|
3802
|
+
}
|
|
3803
|
+
case 1: {
|
|
3804
|
+
const [mapFn] = args;
|
|
3805
|
+
return (array: readonly A[]) => flatMap(array, mapFn);
|
|
3065
3806
|
}
|
|
3066
3807
|
}
|
|
3067
3808
|
}
|
|
@@ -3133,11 +3874,46 @@ export namespace Arr {
|
|
|
3133
3874
|
}
|
|
3134
3875
|
case 1: {
|
|
3135
3876
|
const [chunkSize] = args;
|
|
3136
|
-
return (array
|
|
3877
|
+
return (array) => partition(array, chunkSize);
|
|
3137
3878
|
}
|
|
3138
3879
|
}
|
|
3139
3880
|
}
|
|
3140
3881
|
|
|
3882
|
+
/**
|
|
3883
|
+
* Reverses a tuple, preserving element types in their new positions.
|
|
3884
|
+
*
|
|
3885
|
+
* The type system precisely tracks the reversal, so the returned tuple
|
|
3886
|
+
* has its element types in the exact reverse order. This is more precise
|
|
3887
|
+
* than array reversal which loses positional type information.
|
|
3888
|
+
*
|
|
3889
|
+
* @template T - The tuple type to reverse
|
|
3890
|
+
* @param array - The input tuple
|
|
3891
|
+
* @returns A new tuple with elements in reverse order and precise typing
|
|
3892
|
+
*
|
|
3893
|
+
* @example
|
|
3894
|
+
* ```typescript
|
|
3895
|
+
* // Basic reversal
|
|
3896
|
+
* const nums = [1, 2, 3] as const;
|
|
3897
|
+
* const reversed = Arr.toReversed(nums); // readonly [3, 2, 1]
|
|
3898
|
+
*
|
|
3899
|
+
* // Mixed types preserved in reverse positions
|
|
3900
|
+
* const mixed = [1, 'hello', true, null] as const;
|
|
3901
|
+
* const revMixed = Arr.toReversed(mixed);
|
|
3902
|
+
* // readonly [null, true, 'hello', 1]
|
|
3903
|
+
*
|
|
3904
|
+
* // Empty and single-element tuples
|
|
3905
|
+
* const empty = [] as const;
|
|
3906
|
+
* const revEmpty = Arr.toReversed(empty); // readonly []
|
|
3907
|
+
* const single = [42] as const;
|
|
3908
|
+
* const revSingle = Arr.toReversed(single); // readonly [42]
|
|
3909
|
+
* ```
|
|
3910
|
+
*/
|
|
3911
|
+
export const toReversed = <const Ar extends readonly unknown[]>(
|
|
3912
|
+
array: Ar,
|
|
3913
|
+
): List.Reverse<Ar> =>
|
|
3914
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
3915
|
+
array.toReversed() as never;
|
|
3916
|
+
|
|
3141
3917
|
/**
|
|
3142
3918
|
* Sorts an array by a value derived from its elements, using a numeric mapping.
|
|
3143
3919
|
* @template E The type of elements in the array.
|
|
@@ -3154,17 +3930,66 @@ export namespace Arr {
|
|
|
3154
3930
|
* // [{ name: 'Adam', score: 90 }, { name: 'Bob', score: 80 }, { name: 'Eve', score: 70 }]
|
|
3155
3931
|
* ```
|
|
3156
3932
|
*/
|
|
3157
|
-
export
|
|
3158
|
-
array: readonly
|
|
3159
|
-
|
|
3933
|
+
export const toSorted = <Ar extends readonly unknown[]>(
|
|
3934
|
+
...[array, comparator]: Ar extends readonly number[]
|
|
3935
|
+
? readonly [
|
|
3936
|
+
array: Ar,
|
|
3937
|
+
// If the array elements are mapped to numbers, comparator is optional.
|
|
3938
|
+
comparator?: (x: Ar[number], y: Ar[number]) => number,
|
|
3939
|
+
]
|
|
3940
|
+
: readonly [
|
|
3941
|
+
array: Ar,
|
|
3942
|
+
comparator: (x: Ar[number], y: Ar[number]) => number,
|
|
3943
|
+
]
|
|
3944
|
+
): IsFixedLengthList<Ar> extends true
|
|
3945
|
+
? ArrayOfLength<Ar['length'], Ar[number]>
|
|
3946
|
+
: Ar extends NonEmptyArray<unknown>
|
|
3947
|
+
? NonEmptyArray<Ar[number]>
|
|
3948
|
+
: readonly Ar[number][] =>
|
|
3949
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
3950
|
+
array.toSorted(
|
|
3951
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
3952
|
+
(comparator as ((x: unknown, y: unknown) => number) | undefined) ??
|
|
3953
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
3954
|
+
((x, y) => (x as number) - (y as number)),
|
|
3955
|
+
) as never;
|
|
3956
|
+
|
|
3957
|
+
/**
|
|
3958
|
+
* Sorts an array by a value derived from its elements, using a numeric mapping.
|
|
3959
|
+
* @template E The type of elements in the array.
|
|
3960
|
+
* @param array The input array.
|
|
3961
|
+
* @param comparatorValueMapper A function `(value: A) => number` that maps an element to a number for comparison.
|
|
3962
|
+
* @param comparator An optional custom comparator function `(x: number, y: number) => number` for the mapped numbers. Defaults to ascending sort (x - y).
|
|
3963
|
+
* @returns A new array sorted by the mapped values.
|
|
3964
|
+
* @example
|
|
3965
|
+
* ```ts
|
|
3966
|
+
* const items = [{ name: 'Eve', score: 70 }, { name: 'Adam', score: 90 }, { name: 'Bob', score: 80 }];
|
|
3967
|
+
* Arr.toSortedBy(items, item => item.score);
|
|
3968
|
+
* // [{ name: 'Eve', score: 70 }, { name: 'Bob', score: 80 }, { name: 'Adam', score: 90 }]
|
|
3969
|
+
* Arr.toSortedBy(items, item => item.score, (a, b) => b - a); // Sort descending
|
|
3970
|
+
* // [{ name: 'Adam', score: 90 }, { name: 'Bob', score: 80 }, { name: 'Eve', score: 70 }]
|
|
3971
|
+
* ```
|
|
3972
|
+
*/
|
|
3973
|
+
export function toSortedBy<Ar extends readonly unknown[]>(
|
|
3974
|
+
array: Ar,
|
|
3975
|
+
comparatorValueMapper: (value: Ar[number]) => number,
|
|
3976
|
+
// If the array elements are mapped to numbers, comparator is optional.
|
|
3160
3977
|
comparator?: (x: number, y: number) => number,
|
|
3161
|
-
):
|
|
3978
|
+
): IsFixedLengthList<Ar> extends true
|
|
3979
|
+
? ArrayOfLength<Ar['length'], Ar[number]>
|
|
3980
|
+
: Ar extends NonEmptyArray<unknown>
|
|
3981
|
+
? NonEmptyArray<Ar[number]>
|
|
3982
|
+
: readonly Ar[number][];
|
|
3162
3983
|
|
|
3163
|
-
export function toSortedBy<
|
|
3164
|
-
array:
|
|
3165
|
-
comparatorValueMapper: (value:
|
|
3984
|
+
export function toSortedBy<Ar extends readonly unknown[], const V>(
|
|
3985
|
+
array: Ar,
|
|
3986
|
+
comparatorValueMapper: (value: Ar[number]) => V,
|
|
3166
3987
|
comparator: (x: V, y: V) => number,
|
|
3167
|
-
):
|
|
3988
|
+
): IsFixedLengthList<Ar> extends true
|
|
3989
|
+
? ArrayOfLength<Ar['length'], Ar[number]>
|
|
3990
|
+
: Ar extends NonEmptyArray<unknown>
|
|
3991
|
+
? NonEmptyArray<Ar[number]>
|
|
3992
|
+
: readonly Ar[number][];
|
|
3168
3993
|
|
|
3169
3994
|
export function toSortedBy<E, const V>(
|
|
3170
3995
|
array: readonly E[],
|
|
@@ -3240,8 +4065,8 @@ export namespace Arr {
|
|
|
3240
4065
|
*
|
|
3241
4066
|
* // Running maximum
|
|
3242
4067
|
* const temperatures = [20, 25, 18, 30, 22];
|
|
3243
|
-
* const runningMax = Arr.scan(temperatures, (max, temp) => Math.max(max, temp),
|
|
3244
|
-
* // [
|
|
4068
|
+
* const runningMax = Arr.scan(temperatures, (max, temp) => Math.max(max, temp), Number.NEGATIVE_INFINITY);
|
|
4069
|
+
* // [Number.NEGATIVE_INFINITY, 20, 25, 25, 30, 30]
|
|
3245
4070
|
*
|
|
3246
4071
|
* // Building strings incrementally
|
|
3247
4072
|
* const words = ['Hello', 'beautiful', 'world'];
|
|
@@ -3339,9 +4164,13 @@ export namespace Arr {
|
|
|
3339
4164
|
* @see {@link SizeType.Arr} for the index parameter type
|
|
3340
4165
|
* @see Array.prototype.reduce for the standard reduce function
|
|
3341
4166
|
*/
|
|
3342
|
-
export function scan<
|
|
3343
|
-
array:
|
|
3344
|
-
reducer: (
|
|
4167
|
+
export function scan<Ar extends readonly unknown[], S>(
|
|
4168
|
+
array: Ar,
|
|
4169
|
+
reducer: (
|
|
4170
|
+
accumulator: S,
|
|
4171
|
+
currentValue: Ar[number],
|
|
4172
|
+
currentIndex: ArrayIndex<Ar>,
|
|
4173
|
+
) => S,
|
|
3345
4174
|
init: S,
|
|
3346
4175
|
): NonEmptyArray<S>;
|
|
3347
4176
|
|
|
@@ -3374,7 +4203,7 @@ export namespace Arr {
|
|
|
3374
4203
|
case 3: {
|
|
3375
4204
|
const [array, reducer, init] = args;
|
|
3376
4205
|
const mut_result: MutableNonEmptyArray<S> = castMutable(
|
|
3377
|
-
newArray<S>(asPositiveUint32(array.length + 1), init),
|
|
4206
|
+
newArray<S, PositiveUint32>(asPositiveUint32(array.length + 1), init),
|
|
3378
4207
|
);
|
|
3379
4208
|
|
|
3380
4209
|
let mut_acc = init;
|
|
@@ -3388,7 +4217,7 @@ export namespace Arr {
|
|
|
3388
4217
|
}
|
|
3389
4218
|
case 2: {
|
|
3390
4219
|
const [reducer, init] = args;
|
|
3391
|
-
return (array
|
|
4220
|
+
return (array) => scan(array, reducer, init);
|
|
3392
4221
|
}
|
|
3393
4222
|
}
|
|
3394
4223
|
}
|
|
@@ -3542,10 +4371,13 @@ export namespace Arr {
|
|
|
3542
4371
|
* @see {@link IMap.map} for transforming grouped data
|
|
3543
4372
|
* @see {@link Optional} for handling potentially missing groups
|
|
3544
4373
|
*/
|
|
3545
|
-
export function groupBy<
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
4374
|
+
export function groupBy<
|
|
4375
|
+
Ar extends readonly unknown[],
|
|
4376
|
+
G extends MapSetKeyType,
|
|
4377
|
+
>(
|
|
4378
|
+
array: Ar,
|
|
4379
|
+
grouper: (value: Ar[number], index: ArrayIndex<Ar>) => G,
|
|
4380
|
+
): IMap<G, readonly Ar[number][]>;
|
|
3549
4381
|
|
|
3550
4382
|
export function groupBy<E, G extends MapSetKeyType>(
|
|
3551
4383
|
grouper: (value: E, index: SizeType.Arr) => G,
|
|
@@ -3578,7 +4410,7 @@ export namespace Arr {
|
|
|
3578
4410
|
}
|
|
3579
4411
|
case 1: {
|
|
3580
4412
|
const [grouper] = args;
|
|
3581
|
-
return (array
|
|
4413
|
+
return (array) => groupBy(array, grouper);
|
|
3582
4414
|
}
|
|
3583
4415
|
}
|
|
3584
4416
|
}
|
|
@@ -3594,9 +4426,13 @@ export namespace Arr {
|
|
|
3594
4426
|
* Arr.uniq([1, 2, 2, 3, 1, 4]); // [1, 2, 3, 4]
|
|
3595
4427
|
* ```
|
|
3596
4428
|
*/
|
|
3597
|
-
export const uniq = <
|
|
3598
|
-
array:
|
|
3599
|
-
):
|
|
4429
|
+
export const uniq = <Ar extends readonly Primitive[]>(
|
|
4430
|
+
array: Ar,
|
|
4431
|
+
): Ar extends NonEmptyArray<unknown>
|
|
4432
|
+
? NonEmptyArray<Ar[number]>
|
|
4433
|
+
: readonly Ar[number][] =>
|
|
4434
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
4435
|
+
Array.from(new Set(array)) as never;
|
|
3600
4436
|
|
|
3601
4437
|
/**
|
|
3602
4438
|
* Creates a new array with unique elements from the input array, based on the values returned by `mapFn`.
|
|
@@ -3619,22 +4455,15 @@ export namespace Arr {
|
|
|
3619
4455
|
* Arr.uniqBy(users, user => user.id); // [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]
|
|
3620
4456
|
* ```
|
|
3621
4457
|
*/
|
|
3622
|
-
export
|
|
3623
|
-
array:
|
|
3624
|
-
mapFn: (value:
|
|
3625
|
-
): NonEmptyArray<
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
array: readonly E[],
|
|
3629
|
-
mapFn: (value: E) => P,
|
|
3630
|
-
): readonly E[];
|
|
3631
|
-
|
|
3632
|
-
export function uniqBy<E, P extends Primitive>(
|
|
3633
|
-
array: readonly E[],
|
|
3634
|
-
mapFn: (value: E) => P,
|
|
3635
|
-
): readonly E[] {
|
|
4458
|
+
export const uniqBy = <Ar extends readonly unknown[], P extends Primitive>(
|
|
4459
|
+
array: Ar,
|
|
4460
|
+
mapFn: (value: Ar[number]) => P,
|
|
4461
|
+
): Ar extends NonEmptyArray<unknown>
|
|
4462
|
+
? NonEmptyArray<Ar[number]>
|
|
4463
|
+
: readonly Ar[number][] => {
|
|
3636
4464
|
const mut_mappedValues = new Set<P>();
|
|
3637
4465
|
|
|
4466
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
3638
4467
|
return array.filter((val) => {
|
|
3639
4468
|
const mappedValue = mapFn(val);
|
|
3640
4469
|
|
|
@@ -3642,8 +4471,8 @@ export namespace Arr {
|
|
|
3642
4471
|
mut_mappedValues.add(mappedValue);
|
|
3643
4472
|
|
|
3644
4473
|
return true;
|
|
3645
|
-
});
|
|
3646
|
-
}
|
|
4474
|
+
}) satisfies readonly Ar[number][] as never;
|
|
4475
|
+
};
|
|
3647
4476
|
|
|
3648
4477
|
// set operations & equality
|
|
3649
4478
|
|
|
@@ -3821,6 +4650,100 @@ export namespace Arr {
|
|
|
3821
4650
|
return mut_result;
|
|
3822
4651
|
};
|
|
3823
4652
|
|
|
4653
|
+
// iterators
|
|
4654
|
+
|
|
4655
|
+
/**
|
|
4656
|
+
* Returns an iterable of key-value pairs for every entry in the array.
|
|
4657
|
+
*
|
|
4658
|
+
* This function returns an array where each element is a tuple containing the index and value.
|
|
4659
|
+
* The indices are branded as `SizeType.Arr` for type safety.
|
|
4660
|
+
*
|
|
4661
|
+
* @template Ar The exact type of the input array.
|
|
4662
|
+
* @param array The array to get entries from.
|
|
4663
|
+
* @returns An array of `[index, value]` pairs.
|
|
4664
|
+
*
|
|
4665
|
+
* @example
|
|
4666
|
+
* ```typescript
|
|
4667
|
+
* // Direct usage
|
|
4668
|
+
* const fruits = ['apple', 'banana', 'cherry'];
|
|
4669
|
+
* const entries = Arr.entries(fruits); // [[0, 'apple'], [1, 'banana'], [2, 'cherry']]
|
|
4670
|
+
*
|
|
4671
|
+
* // Curried usage
|
|
4672
|
+
* const getEntries = Arr.entries;
|
|
4673
|
+
* const result = getEntries(['a', 'b']); // [[0, 'a'], [1, 'b']]
|
|
4674
|
+
*
|
|
4675
|
+
* // With tuples
|
|
4676
|
+
* const tuple = [10, 20, 30] as const;
|
|
4677
|
+
* const tupleEntries = Arr.entries(tuple); // [[0, 10], [1, 20], [2, 30]]
|
|
4678
|
+
* ```
|
|
4679
|
+
*/
|
|
4680
|
+
export function* entries<E>(
|
|
4681
|
+
array: readonly E[],
|
|
4682
|
+
): ArrayIterator<readonly [SizeType.Arr, E]> {
|
|
4683
|
+
for (const [index, value] of array.entries()) {
|
|
4684
|
+
yield [asUint32(index), value] as const;
|
|
4685
|
+
}
|
|
4686
|
+
}
|
|
4687
|
+
|
|
4688
|
+
/**
|
|
4689
|
+
* Returns an iterable of values in the array.
|
|
4690
|
+
*
|
|
4691
|
+
* This function is essentially an identity function that returns a copy of the array.
|
|
4692
|
+
* It's included for API completeness and consistency with native Array methods.
|
|
4693
|
+
*
|
|
4694
|
+
* @template Ar The exact type of the input array.
|
|
4695
|
+
* @param array The array to get values from.
|
|
4696
|
+
* @returns A copy of the input array.
|
|
4697
|
+
*
|
|
4698
|
+
* @example
|
|
4699
|
+
* ```typescript
|
|
4700
|
+
* // Direct usage
|
|
4701
|
+
* const numbers = [1, 2, 3];
|
|
4702
|
+
* const values = Arr.values(numbers); // [1, 2, 3]
|
|
4703
|
+
*
|
|
4704
|
+
* // Curried usage
|
|
4705
|
+
* const getValues = Arr.values;
|
|
4706
|
+
* const result = getValues(['a', 'b']); // ['a', 'b']
|
|
4707
|
+
* ```
|
|
4708
|
+
*/
|
|
4709
|
+
export function* values<E>(array: readonly E[]): ArrayIterator<E> {
|
|
4710
|
+
for (const value of array.values()) {
|
|
4711
|
+
yield value;
|
|
4712
|
+
}
|
|
4713
|
+
}
|
|
4714
|
+
|
|
4715
|
+
/**
|
|
4716
|
+
* Returns an iterable of keys in the array.
|
|
4717
|
+
*
|
|
4718
|
+
* This function returns an array of branded indices (`SizeType.Arr`) for type safety.
|
|
4719
|
+
*
|
|
4720
|
+
* @template Ar The exact type of the input array.
|
|
4721
|
+
* @param array The array to get indices from.
|
|
4722
|
+
* @returns An array of indices.
|
|
4723
|
+
*
|
|
4724
|
+
* @example
|
|
4725
|
+
* ```typescript
|
|
4726
|
+
* // Direct usage
|
|
4727
|
+
* const fruits = ['apple', 'banana', 'cherry'];
|
|
4728
|
+
* const indices = Arr.indices(fruits); // [0, 1, 2]
|
|
4729
|
+
*
|
|
4730
|
+
* // Curried usage
|
|
4731
|
+
* const getIndices = Arr.indices;
|
|
4732
|
+
* const result = getIndices(['a', 'b']); // [0, 1]
|
|
4733
|
+
*
|
|
4734
|
+
* // Empty array
|
|
4735
|
+
* const empty: string[] = [];
|
|
4736
|
+
* const emptyIndices = Arr.indices(empty); // []
|
|
4737
|
+
* ```
|
|
4738
|
+
*/
|
|
4739
|
+
export function* indices<E>(
|
|
4740
|
+
array: readonly E[],
|
|
4741
|
+
): ArrayIterator<SizeType.Arr> {
|
|
4742
|
+
for (const key of array.keys()) {
|
|
4743
|
+
yield asUint32(key);
|
|
4744
|
+
}
|
|
4745
|
+
}
|
|
4746
|
+
|
|
3824
4747
|
// aliases
|
|
3825
4748
|
|
|
3826
4749
|
/**
|
|
@@ -3858,4 +4781,22 @@ export namespace Arr {
|
|
|
3858
4781
|
* @see {@link partition}
|
|
3859
4782
|
*/
|
|
3860
4783
|
export const chunk = partition;
|
|
4784
|
+
|
|
4785
|
+
/**
|
|
4786
|
+
* Alias for `create`. Creates a new array of the specified length, with each position filled with the provided initial value.
|
|
4787
|
+
* @see {@link create}
|
|
4788
|
+
*/
|
|
4789
|
+
export const newArray = create;
|
|
4790
|
+
|
|
4791
|
+
/**
|
|
4792
|
+
* Alias for `size`. Returns the length of an array.
|
|
4793
|
+
* @see {@link size}
|
|
4794
|
+
*/
|
|
4795
|
+
export const length = size;
|
|
4796
|
+
|
|
4797
|
+
/**
|
|
4798
|
+
* Alias for `indices`. Returns an iterable of keys in the array.
|
|
4799
|
+
* @see {@link indices}
|
|
4800
|
+
*/
|
|
4801
|
+
export const keys = indices;
|
|
3861
4802
|
}
|