ts-data-forge 14.9.0 → 14.10.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 +5 -5
- package/dist/array/impl/array-utils-element-access.d.mts.map +1 -1
- package/dist/array/impl/array-utils-element-access.mjs +4 -4
- package/dist/array/impl/array-utils-element-access.mjs.map +1 -1
- package/dist/array/impl/array-utils-length-bounded-array-cast.d.mts +8 -8
- package/dist/array/impl/array-utils-length-bounded-array-cast.d.mts.map +1 -1
- package/dist/array/impl/array-utils-length-bounded-array-cast.mjs +28 -28
- package/dist/array/impl/array-utils-length-bounded-array-cast.mjs.map +1 -1
- package/dist/array/impl/array-utils-length-bounded-array-guard.d.mts.map +1 -1
- package/dist/array/impl/array-utils-length-bounded-array-guard.mjs +4 -4
- package/dist/array/impl/array-utils-length-bounded-array-guard.mjs.map +1 -1
- package/dist/array/impl/array-utils-length-bounded-tuple-cast.d.mts +3 -4
- package/dist/array/impl/array-utils-length-bounded-tuple-cast.d.mts.map +1 -1
- package/dist/array/impl/array-utils-length-bounded-tuple-cast.mjs +28 -29
- package/dist/array/impl/array-utils-length-bounded-tuple-cast.mjs.map +1 -1
- package/dist/array/impl/array-utils-length-bounded-tuple-guard.d.mts.map +1 -1
- package/dist/array/impl/array-utils-length-bounded-tuple-guard.mjs +3 -3
- package/dist/array/impl/array-utils-length-bounded-tuple-guard.mjs.map +1 -1
- package/dist/array/impl/array-utils-modification.d.mts +1 -1
- package/dist/array/impl/array-utils-modification.d.mts.map +1 -1
- package/dist/array/impl/array-utils-modification.mjs +15 -15
- package/dist/array/impl/array-utils-modification.mjs.map +1 -1
- package/dist/array/impl/array-utils-reducing-value.d.mts.map +1 -1
- package/dist/array/impl/array-utils-reducing-value.mjs +12 -12
- package/dist/array/impl/array-utils-reducing-value.mjs.map +1 -1
- package/dist/array/impl/array-utils-search.d.mts.map +1 -1
- package/dist/array/impl/array-utils-search.mjs +56 -56
- package/dist/array/impl/array-utils-search.mjs.map +1 -1
- package/dist/array/impl/array-utils-slicing.d.mts.map +1 -1
- package/dist/array/impl/array-utils-slicing.mjs +3 -3
- package/dist/array/impl/array-utils-slicing.mjs.map +1 -1
- package/dist/array/impl/array-utils-transformation.d.mts +25 -25
- package/dist/array/impl/array-utils-transformation.d.mts.map +1 -1
- package/dist/array/impl/array-utils-transformation.mjs +22 -22
- package/dist/array/impl/array-utils-transformation.mjs.map +1 -1
- package/dist/array/impl/array-utils-validation.d.mts.map +1 -1
- package/dist/array/impl/array-utils-validation.mjs +2 -2
- package/dist/array/impl/array-utils-validation.mjs.map +1 -1
- package/dist/collections/imap-mapped.d.mts +2 -2
- package/dist/collections/imap.d.mts +3 -4
- package/dist/collections/imap.d.mts.map +1 -1
- package/dist/collections/imap.mjs +0 -1
- package/dist/collections/imap.mjs.map +1 -1
- package/dist/collections/iset-mapped.d.mts +1 -2
- package/dist/collections/iset-mapped.d.mts.map +1 -1
- package/dist/collections/iset-mapped.mjs.map +1 -1
- package/dist/collections/iset.d.mts +4 -5
- package/dist/collections/iset.d.mts.map +1 -1
- package/dist/collections/iset.mjs +0 -1
- package/dist/collections/iset.mjs.map +1 -1
- package/dist/number/num.d.mts +2 -2
- package/dist/number/num.mjs.map +1 -1
- package/dist/object/object.d.mts +2 -2
- package/dist/others/fast-deep-equal.d.mts.map +1 -1
- package/dist/others/fast-deep-equal.mjs +10 -7
- package/dist/others/fast-deep-equal.mjs.map +1 -1
- package/dist/others/index.d.mts +1 -0
- package/dist/others/index.d.mts.map +1 -1
- package/dist/others/index.mjs +1 -0
- package/dist/others/index.mjs.map +1 -1
- package/dist/others/replace-equal-deep.d.mts +95 -0
- package/dist/others/replace-equal-deep.d.mts.map +1 -0
- package/dist/others/replace-equal-deep.mjs +156 -0
- package/dist/others/replace-equal-deep.mjs.map +1 -0
- package/dist/string/str.d.mts +2 -2
- package/package.json +12 -12
- package/src/array/impl/array-utils-element-access.mts +11 -11
- package/src/array/impl/array-utils-length-bounded-array-cast.mts +69 -69
- package/src/array/impl/array-utils-length-bounded-array-guard.mts +21 -21
- package/src/array/impl/array-utils-length-bounded-array-guard.test.mts +2 -2
- package/src/array/impl/array-utils-length-bounded-tuple-cast.mts +64 -65
- package/src/array/impl/array-utils-length-bounded-tuple-guard.mts +15 -15
- package/src/array/impl/array-utils-modification.mts +54 -54
- package/src/array/impl/array-utils-reducing-value.mts +55 -55
- package/src/array/impl/array-utils-search.mts +114 -114
- package/src/array/impl/array-utils-slicing.mts +16 -16
- package/src/array/impl/array-utils-transformation.mts +96 -96
- package/src/array/impl/array-utils-transformation.test.mts +2 -2
- package/src/array/impl/array-utils-validation.mts +19 -19
- package/src/array/impl/array-utils-validation.test.mts +1 -1
- package/src/collections/imap-mapped.mts +2 -2
- package/src/collections/imap.mts +3 -4
- package/src/collections/imap.test.mts +1 -1
- package/src/collections/iset-mapped.mts +1 -2
- package/src/collections/iset.mts +4 -5
- package/src/collections/iset.test.mts +1 -1
- package/src/number/num.mts +10 -10
- package/src/object/object.mts +2 -2
- package/src/others/fast-deep-equal.mts +17 -10
- package/src/others/fast-deep-equal.test.mts +141 -29
- package/src/others/index.mts +1 -0
- package/src/others/replace-equal-deep.mts +225 -0
- package/src/others/replace-equal-deep.test.mts +348 -0
- package/src/string/str.mts +2 -2
|
@@ -70,38 +70,6 @@ export function find<E>(
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
const findImpl = <E,>(
|
|
74
|
-
array: readonly E[],
|
|
75
|
-
predicate: (value: E, index: SizeType.Arr, arr: readonly E[]) => boolean,
|
|
76
|
-
): Optional<E> => {
|
|
77
|
-
const foundIndex = array.findIndex(
|
|
78
|
-
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
79
|
-
predicate as () => boolean,
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
// Left as a comment rather than asserted. This pinned the shape of the
|
|
83
|
-
// standard library's `findIndex`, and the shape differs between the stock
|
|
84
|
-
// library and the strict one — `(value, index, obj: this) => boolean` there
|
|
85
|
-
// against `(value, index, arr: readonly E[]) => unknown` here. `src` ships
|
|
86
|
-
// to consumers so that "Go to Definition" reaches it, so an assertion that
|
|
87
|
-
// only holds under one of them shows up as an error in their editor.
|
|
88
|
-
//
|
|
89
|
-
// expectType<
|
|
90
|
-
// Parameters<typeof array.findIndex>[0],
|
|
91
|
-
// (value: E, index: number, arr: readonly E[]) => unknown
|
|
92
|
-
// >('=');
|
|
93
|
-
|
|
94
|
-
expectType<
|
|
95
|
-
typeof predicate,
|
|
96
|
-
(value: E, index: SizeType.Arr, arr: readonly E[]) => boolean
|
|
97
|
-
>('=');
|
|
98
|
-
|
|
99
|
-
return foundIndex === -1
|
|
100
|
-
? Optional.none
|
|
101
|
-
: // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
102
|
-
Optional.some(array[foundIndex]!);
|
|
103
|
-
};
|
|
104
|
-
|
|
105
73
|
/**
|
|
106
74
|
* Finds the last element that satisfies a predicate.
|
|
107
75
|
*
|
|
@@ -160,38 +128,6 @@ export function findLast<E>(
|
|
|
160
128
|
}
|
|
161
129
|
}
|
|
162
130
|
|
|
163
|
-
const findLastImpl = <E,>(
|
|
164
|
-
array: readonly E[],
|
|
165
|
-
predicate: (value: E, index: SizeType.Arr, arr: readonly E[]) => boolean,
|
|
166
|
-
): Optional<E> => {
|
|
167
|
-
const foundIndex = array.findLastIndex(
|
|
168
|
-
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
169
|
-
predicate as () => boolean,
|
|
170
|
-
);
|
|
171
|
-
|
|
172
|
-
// Left as a comment rather than asserted. This pinned the shape of the
|
|
173
|
-
// standard library's `findIndex`, and the shape differs between the stock
|
|
174
|
-
// library and the strict one — `(value, index, obj: this) => boolean` there
|
|
175
|
-
// against `(value, index, arr: readonly E[]) => unknown` here. `src` ships
|
|
176
|
-
// to consumers so that "Go to Definition" reaches it, so an assertion that
|
|
177
|
-
// only holds under one of them shows up as an error in their editor.
|
|
178
|
-
//
|
|
179
|
-
// expectType<
|
|
180
|
-
// Parameters<typeof array.findIndex>[0],
|
|
181
|
-
// (value: E, index: number, arr: readonly E[]) => unknown
|
|
182
|
-
// >('=');
|
|
183
|
-
|
|
184
|
-
expectType<
|
|
185
|
-
typeof predicate,
|
|
186
|
-
(value: E, index: SizeType.Arr, arr: readonly E[]) => boolean
|
|
187
|
-
>('=');
|
|
188
|
-
|
|
189
|
-
return foundIndex === -1
|
|
190
|
-
? Optional.none
|
|
191
|
-
: // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
192
|
-
Optional.some(array[foundIndex]!);
|
|
193
|
-
};
|
|
194
|
-
|
|
195
131
|
/**
|
|
196
132
|
* Finds the index of the first element that satisfies a predicate.
|
|
197
133
|
*
|
|
@@ -247,17 +183,6 @@ export function findIndex<E>(
|
|
|
247
183
|
}
|
|
248
184
|
}
|
|
249
185
|
|
|
250
|
-
const findIndexImpl = <E,>(
|
|
251
|
-
array: readonly E[],
|
|
252
|
-
predicate: (value: E, index: SizeType.Arr, arr: readonly E[]) => boolean,
|
|
253
|
-
): SizeType.Arr | -1 =>
|
|
254
|
-
pipe(
|
|
255
|
-
array.findIndex(
|
|
256
|
-
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
257
|
-
predicate as (value: E, index: number) => boolean,
|
|
258
|
-
),
|
|
259
|
-
).map((idx) => (idx >= 0 ? asUint32(idx) : -1)).value;
|
|
260
|
-
|
|
261
186
|
/**
|
|
262
187
|
* Finds the index of the last element that satisfies a predicate.
|
|
263
188
|
*
|
|
@@ -313,17 +238,6 @@ export function findLastIndex<E>(
|
|
|
313
238
|
}
|
|
314
239
|
}
|
|
315
240
|
|
|
316
|
-
const findLastIndexImpl = <E,>(
|
|
317
|
-
array: readonly E[],
|
|
318
|
-
predicate: (value: E, index: SizeType.Arr, arr: readonly E[]) => boolean,
|
|
319
|
-
): SizeType.Arr | -1 =>
|
|
320
|
-
pipe(
|
|
321
|
-
array.findLastIndex(
|
|
322
|
-
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
323
|
-
predicate as (value: E, index: number) => boolean,
|
|
324
|
-
),
|
|
325
|
-
).map((idx) => (idx >= 0 ? asUint32(idx) : -1)).value;
|
|
326
|
-
|
|
327
241
|
/**
|
|
328
242
|
* Gets the index of a value in an array.
|
|
329
243
|
*
|
|
@@ -371,15 +285,6 @@ export function indexOf<E>(
|
|
|
371
285
|
}
|
|
372
286
|
}
|
|
373
287
|
|
|
374
|
-
const indexOfImpl = <E,>(
|
|
375
|
-
array: readonly E[],
|
|
376
|
-
searchElement: E,
|
|
377
|
-
): SizeType.Arr | -1 => {
|
|
378
|
-
const index = array.indexOf(searchElement);
|
|
379
|
-
|
|
380
|
-
return index !== -1 ? asUint32(index) : -1;
|
|
381
|
-
};
|
|
382
|
-
|
|
383
288
|
/**
|
|
384
289
|
* Gets the index of a value in an array, starting from a specified index.
|
|
385
290
|
*
|
|
@@ -440,16 +345,6 @@ export function indexOfFrom<E>(
|
|
|
440
345
|
}
|
|
441
346
|
}
|
|
442
347
|
|
|
443
|
-
const indexOfFromImpl = <E,>(
|
|
444
|
-
array: readonly E[],
|
|
445
|
-
searchElement: E,
|
|
446
|
-
fromIndex: SizeType.ArgArrWithNegative,
|
|
447
|
-
): SizeType.Arr | -1 => {
|
|
448
|
-
const index = array.indexOf(searchElement, fromIndex);
|
|
449
|
-
|
|
450
|
-
return index !== -1 ? asUint32(index) : -1;
|
|
451
|
-
};
|
|
452
|
-
|
|
453
348
|
/**
|
|
454
349
|
* Gets the last index of a value in an array.
|
|
455
350
|
*
|
|
@@ -501,15 +396,6 @@ export function lastIndexOf<E>(
|
|
|
501
396
|
}
|
|
502
397
|
}
|
|
503
398
|
|
|
504
|
-
const lastIndexOfImpl = <E,>(
|
|
505
|
-
array: readonly E[],
|
|
506
|
-
searchElement: E,
|
|
507
|
-
): SizeType.Arr | -1 => {
|
|
508
|
-
const index = array.lastIndexOf(searchElement);
|
|
509
|
-
|
|
510
|
-
return index !== -1 ? asUint32(index) : -1;
|
|
511
|
-
};
|
|
512
|
-
|
|
513
399
|
/**
|
|
514
400
|
* Gets the last index of a value in an array, starting from a specified index.
|
|
515
401
|
*
|
|
@@ -570,6 +456,120 @@ export function lastIndexOfFrom<E>(
|
|
|
570
456
|
}
|
|
571
457
|
}
|
|
572
458
|
|
|
459
|
+
const findImpl = <E,>(
|
|
460
|
+
array: readonly E[],
|
|
461
|
+
predicate: (value: E, index: SizeType.Arr, arr: readonly E[]) => boolean,
|
|
462
|
+
): Optional<E> => {
|
|
463
|
+
const foundIndex = array.findIndex(
|
|
464
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
465
|
+
predicate as () => boolean,
|
|
466
|
+
);
|
|
467
|
+
|
|
468
|
+
// Left as a comment rather than asserted. This pinned the shape of the
|
|
469
|
+
// standard library's `findIndex`, and the shape differs between the stock
|
|
470
|
+
// library and the strict one — `(value, index, obj: this) => boolean` there
|
|
471
|
+
// against `(value, index, arr: readonly E[]) => unknown` here. `src` ships to
|
|
472
|
+
// consumers so that "Go to Definition" reaches it, so an assertion that only
|
|
473
|
+
// holds under one of them shows up as an error in their editor.
|
|
474
|
+
//
|
|
475
|
+
// expectType<
|
|
476
|
+
// Parameters<typeof array.findIndex>[0],
|
|
477
|
+
// (value: E, index: number, arr: readonly E[]) => unknown
|
|
478
|
+
// >('=');
|
|
479
|
+
|
|
480
|
+
expectType<
|
|
481
|
+
typeof predicate,
|
|
482
|
+
(value: E, index: SizeType.Arr, arr: readonly E[]) => boolean
|
|
483
|
+
>('=');
|
|
484
|
+
|
|
485
|
+
return foundIndex === -1
|
|
486
|
+
? Optional.none
|
|
487
|
+
: // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
488
|
+
Optional.some(array[foundIndex]!);
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
const findLastImpl = <E,>(
|
|
492
|
+
array: readonly E[],
|
|
493
|
+
predicate: (value: E, index: SizeType.Arr, arr: readonly E[]) => boolean,
|
|
494
|
+
): Optional<E> => {
|
|
495
|
+
const foundIndex = array.findLastIndex(
|
|
496
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
497
|
+
predicate as () => boolean,
|
|
498
|
+
);
|
|
499
|
+
|
|
500
|
+
// Left as a comment rather than asserted. This pinned the shape of the
|
|
501
|
+
// standard library's `findIndex`, and the shape differs between the stock
|
|
502
|
+
// library and the strict one — `(value, index, obj: this) => boolean` there
|
|
503
|
+
// against `(value, index, arr: readonly E[]) => unknown` here. `src` ships to
|
|
504
|
+
// consumers so that "Go to Definition" reaches it, so an assertion that only
|
|
505
|
+
// holds under one of them shows up as an error in their editor.
|
|
506
|
+
//
|
|
507
|
+
// expectType<
|
|
508
|
+
// Parameters<typeof array.findIndex>[0],
|
|
509
|
+
// (value: E, index: number, arr: readonly E[]) => unknown
|
|
510
|
+
// >('=');
|
|
511
|
+
|
|
512
|
+
expectType<
|
|
513
|
+
typeof predicate,
|
|
514
|
+
(value: E, index: SizeType.Arr, arr: readonly E[]) => boolean
|
|
515
|
+
>('=');
|
|
516
|
+
|
|
517
|
+
return foundIndex === -1
|
|
518
|
+
? Optional.none
|
|
519
|
+
: // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
520
|
+
Optional.some(array[foundIndex]!);
|
|
521
|
+
};
|
|
522
|
+
|
|
523
|
+
const findIndexImpl = <E,>(
|
|
524
|
+
array: readonly E[],
|
|
525
|
+
predicate: (value: E, index: SizeType.Arr, arr: readonly E[]) => boolean,
|
|
526
|
+
): SizeType.Arr | -1 =>
|
|
527
|
+
pipe(
|
|
528
|
+
array.findIndex(
|
|
529
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
530
|
+
predicate as (value: E, index: number) => boolean,
|
|
531
|
+
),
|
|
532
|
+
).map((idx) => (idx >= 0 ? asUint32(idx) : -1)).value;
|
|
533
|
+
|
|
534
|
+
const findLastIndexImpl = <E,>(
|
|
535
|
+
array: readonly E[],
|
|
536
|
+
predicate: (value: E, index: SizeType.Arr, arr: readonly E[]) => boolean,
|
|
537
|
+
): SizeType.Arr | -1 =>
|
|
538
|
+
pipe(
|
|
539
|
+
array.findLastIndex(
|
|
540
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
541
|
+
predicate as (value: E, index: number) => boolean,
|
|
542
|
+
),
|
|
543
|
+
).map((idx) => (idx >= 0 ? asUint32(idx) : -1)).value;
|
|
544
|
+
|
|
545
|
+
const indexOfImpl = <E,>(
|
|
546
|
+
array: readonly E[],
|
|
547
|
+
searchElement: E,
|
|
548
|
+
): SizeType.Arr | -1 => {
|
|
549
|
+
const index = array.indexOf(searchElement);
|
|
550
|
+
|
|
551
|
+
return index !== -1 ? asUint32(index) : -1;
|
|
552
|
+
};
|
|
553
|
+
|
|
554
|
+
const indexOfFromImpl = <E,>(
|
|
555
|
+
array: readonly E[],
|
|
556
|
+
searchElement: E,
|
|
557
|
+
fromIndex: SizeType.ArgArrWithNegative,
|
|
558
|
+
): SizeType.Arr | -1 => {
|
|
559
|
+
const index = array.indexOf(searchElement, fromIndex);
|
|
560
|
+
|
|
561
|
+
return index !== -1 ? asUint32(index) : -1;
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
const lastIndexOfImpl = <E,>(
|
|
565
|
+
array: readonly E[],
|
|
566
|
+
searchElement: E,
|
|
567
|
+
): SizeType.Arr | -1 => {
|
|
568
|
+
const index = array.lastIndexOf(searchElement);
|
|
569
|
+
|
|
570
|
+
return index !== -1 ? asUint32(index) : -1;
|
|
571
|
+
};
|
|
572
|
+
|
|
573
573
|
const lastIndexOfFromImpl = <E,>(
|
|
574
574
|
array: readonly E[],
|
|
575
575
|
searchElement: E,
|
|
@@ -131,11 +131,6 @@ export function take<E>(
|
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
const takeImpl = <E,>(
|
|
135
|
-
array: readonly E[],
|
|
136
|
-
num: SizeType.ArgArr,
|
|
137
|
-
): readonly E[] => sliceClamped(array, 0, num);
|
|
138
|
-
|
|
139
134
|
/**
|
|
140
135
|
* Takes the last N elements from an array.
|
|
141
136
|
*
|
|
@@ -197,12 +192,6 @@ export function takeLast<E>(
|
|
|
197
192
|
}
|
|
198
193
|
}
|
|
199
194
|
|
|
200
|
-
const takeLastImpl = <E,>(
|
|
201
|
-
array: readonly E[],
|
|
202
|
-
num: SizeType.ArgArr,
|
|
203
|
-
): readonly E[] =>
|
|
204
|
-
sliceClamped(array, Uint32.sub(size(array), num), size(array));
|
|
205
|
-
|
|
206
195
|
/**
|
|
207
196
|
* Skips the first N elements of an array.
|
|
208
197
|
*
|
|
@@ -255,11 +244,6 @@ export function skip<E>(
|
|
|
255
244
|
}
|
|
256
245
|
}
|
|
257
246
|
|
|
258
|
-
const skipImpl = <E,>(
|
|
259
|
-
array: readonly E[],
|
|
260
|
-
num: SizeType.ArgArr,
|
|
261
|
-
): readonly E[] => sliceClamped(array, num, size(array));
|
|
262
|
-
|
|
263
247
|
/**
|
|
264
248
|
* Skips the last N elements of an array.
|
|
265
249
|
*
|
|
@@ -314,6 +298,22 @@ export function skipLast<E>(
|
|
|
314
298
|
}
|
|
315
299
|
}
|
|
316
300
|
|
|
301
|
+
const takeImpl = <E,>(
|
|
302
|
+
array: readonly E[],
|
|
303
|
+
num: SizeType.ArgArr,
|
|
304
|
+
): readonly E[] => sliceClamped(array, 0, num);
|
|
305
|
+
|
|
306
|
+
const takeLastImpl = <E,>(
|
|
307
|
+
array: readonly E[],
|
|
308
|
+
num: SizeType.ArgArr,
|
|
309
|
+
): readonly E[] =>
|
|
310
|
+
sliceClamped(array, Uint32.sub(size(array), num), size(array));
|
|
311
|
+
|
|
312
|
+
const skipImpl = <E,>(
|
|
313
|
+
array: readonly E[],
|
|
314
|
+
num: SizeType.ArgArr,
|
|
315
|
+
): readonly E[] => sliceClamped(array, num, size(array));
|
|
316
|
+
|
|
317
317
|
const skipLastImpl = <E,>(
|
|
318
318
|
array: readonly E[],
|
|
319
319
|
num: SizeType.ArgArr,
|
|
@@ -48,8 +48,8 @@ export function map<const Ar extends readonly unknown[] & UnknownBrand, B>(
|
|
|
48
48
|
mapFn: (a: Ar[number], index: ArrayIndex<Ar>) => B,
|
|
49
49
|
): ChangeArrayElement<Ar, B>;
|
|
50
50
|
|
|
51
|
-
// A plain array or tuple carries no length brand, so the homomorphic mapping
|
|
52
|
-
//
|
|
51
|
+
// A plain array or tuple carries no length brand, so the homomorphic mapping is
|
|
52
|
+
// the whole answer. Stating it directly — rather than going through
|
|
53
53
|
// `ChangeArrayElement`, whose `HasLengthConstraint` test a *generic* `Ar`
|
|
54
54
|
// cannot decide — is what keeps `map` usable inside a function that is itself
|
|
55
55
|
// generic over the tuple: a deferred conditional is not assignable to the
|
|
@@ -68,8 +68,8 @@ export function map<const Ar extends readonly unknown[], B>(
|
|
|
68
68
|
//
|
|
69
69
|
// Spelled as an intersection of two function types rather than one object type
|
|
70
70
|
// carrying two call signatures — the `convert-to-readonly` codemod wraps an
|
|
71
|
-
// inline object type in `Readonly<…>`, and a mapped type drops call
|
|
72
|
-
//
|
|
71
|
+
// inline object type in `Readonly<…>`, and a mapped type drops call signatures,
|
|
72
|
+
// which would leave the curried form with none at all.
|
|
73
73
|
export function map<A, B>(
|
|
74
74
|
mapFn: (a: A, index: SizeType.Arr) => B,
|
|
75
75
|
): (<const Ar extends readonly A[] & UnknownBrand>(
|
|
@@ -175,26 +175,6 @@ export function scan<E, S>(
|
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
-
const scanImpl = <E, S>(
|
|
179
|
-
array: readonly E[],
|
|
180
|
-
reducer: (accumulator: S, currentValue: E, currentIndex: SizeType.Arr) => S,
|
|
181
|
-
init: S,
|
|
182
|
-
): NonEmptyTuple<S> => {
|
|
183
|
-
const mut_result = castMutable<NonEmptyTuple<S>>(
|
|
184
|
-
newArray<PositiveUint32, S>(asPositiveUint32(array.length + 1), init),
|
|
185
|
-
);
|
|
186
|
-
|
|
187
|
-
let mut_acc = init;
|
|
188
|
-
|
|
189
|
-
for (const [index, value] of array.entries()) {
|
|
190
|
-
mut_acc = reducer(mut_acc, value, asUint32(index));
|
|
191
|
-
|
|
192
|
-
mut_result[index + 1] = mut_acc;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
return mut_result;
|
|
196
|
-
};
|
|
197
|
-
|
|
198
178
|
/**
|
|
199
179
|
* Reverses an array.
|
|
200
180
|
*
|
|
@@ -277,16 +257,6 @@ export function toSorted(
|
|
|
277
257
|
);
|
|
278
258
|
}
|
|
279
259
|
|
|
280
|
-
/** The result of sorting `Ar`: same elements, same length, same bounds. */
|
|
281
|
-
type SortedResult<Ar extends readonly unknown[]> =
|
|
282
|
-
HasLengthConstraint<Ar> extends true
|
|
283
|
-
? ChangeArrayElement<Ar, Ar[number]>
|
|
284
|
-
: IsFixedLengthList<Ar> extends true
|
|
285
|
-
? FixedLengthTuple<Ar['length'], Ar[number]>
|
|
286
|
-
: Ar extends NonEmptyTuple<unknown>
|
|
287
|
-
? NonEmptyArray<Ar[number]>
|
|
288
|
-
: readonly Ar[number][];
|
|
289
|
-
|
|
290
260
|
/**
|
|
291
261
|
* Sorts an array by a mapped value.
|
|
292
262
|
*
|
|
@@ -426,11 +396,6 @@ export function filter<E>(
|
|
|
426
396
|
}
|
|
427
397
|
}
|
|
428
398
|
|
|
429
|
-
const filterImpl = <E,>(
|
|
430
|
-
array: readonly E[],
|
|
431
|
-
predicate: (a: E, index: SizeType.Arr) => boolean,
|
|
432
|
-
): readonly E[] => array.filter((a, i) => predicate(a, asUint32(i)));
|
|
433
|
-
|
|
434
399
|
/**
|
|
435
400
|
* Filters an array by excluding elements for which the predicate returns true.
|
|
436
401
|
*
|
|
@@ -474,11 +439,6 @@ export function filterNot<E>(
|
|
|
474
439
|
}
|
|
475
440
|
}
|
|
476
441
|
|
|
477
|
-
const filterNotImpl = <E,>(
|
|
478
|
-
array: readonly E[],
|
|
479
|
-
predicate: (a: E, index: SizeType.Arr) => boolean,
|
|
480
|
-
): readonly E[] => array.filter((a, i) => !predicate(a, asUint32(i)));
|
|
481
|
-
|
|
482
442
|
/**
|
|
483
443
|
* Creates a new array with unique elements.
|
|
484
444
|
*
|
|
@@ -615,11 +575,6 @@ export function flat<E, D extends SafeUintWithSmallInt = 1>(
|
|
|
615
575
|
}
|
|
616
576
|
}
|
|
617
577
|
|
|
618
|
-
const flatImpl = (
|
|
619
|
-
array: readonly unknown[],
|
|
620
|
-
depth?: SafeUintWithSmallInt,
|
|
621
|
-
): readonly unknown[] => array.flat(depth);
|
|
622
|
-
|
|
623
578
|
/**
|
|
624
579
|
* Maps each element and flattens the result.
|
|
625
580
|
*
|
|
@@ -734,37 +689,6 @@ export function partition<
|
|
|
734
689
|
}
|
|
735
690
|
}
|
|
736
691
|
|
|
737
|
-
/**
|
|
738
|
-
* Element type of {@link partition}'s result: a chunk holds between 1 and `N`
|
|
739
|
-
* elements. The lower bound is what makes this worth spelling out — `partition`
|
|
740
|
-
* never emits an empty chunk, so indexed access into a chunk is not
|
|
741
|
-
* `undefined` at position `0`, unlike with a plain `readonly E[]`.
|
|
742
|
-
*
|
|
743
|
-
* Falls back to {@link NonEmptyArray} when `N` is not a bound the brand can
|
|
744
|
-
* express, which keeps that lower bound in every case.
|
|
745
|
-
*/
|
|
746
|
-
type PartitionChunk<N, E> = N extends SupportedLength
|
|
747
|
-
? BoundedLengthArray<1, N, E>
|
|
748
|
-
: NonEmptyArray<E>;
|
|
749
|
-
|
|
750
|
-
const partitionImpl = <E, N extends WithSmallInt<PositiveInt & SizeType.Arr>>(
|
|
751
|
-
array: readonly E[],
|
|
752
|
-
chunkSize: N,
|
|
753
|
-
): readonly (readonly E[])[] =>
|
|
754
|
-
chunkSize < 2
|
|
755
|
-
? ([] as const)
|
|
756
|
-
: // eslint-disable-next-line total-functions/no-partial-division
|
|
757
|
-
seq(asUint32(Math.ceil(array.length / chunkSize))).map((i: Uint32) =>
|
|
758
|
-
array.slice(chunkSize * i, chunkSize * (i + 1)),
|
|
759
|
-
);
|
|
760
|
-
|
|
761
|
-
/**
|
|
762
|
-
* Alias for `partition`.
|
|
763
|
-
*
|
|
764
|
-
* @see {@link partition}
|
|
765
|
-
*/
|
|
766
|
-
export const chunk = partition;
|
|
767
|
-
|
|
768
692
|
/**
|
|
769
693
|
* Concatenates two arrays.
|
|
770
694
|
*
|
|
@@ -805,22 +729,6 @@ export const concat = <
|
|
|
805
729
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
806
730
|
[...array1, ...array2] as never;
|
|
807
731
|
|
|
808
|
-
/**
|
|
809
|
-
* Return type of {@link concat}: the concatenated tuple `readonly [...Ar1,
|
|
810
|
-
* ...Ar2]`, additionally branded as {@link NonEmptyArray} when either input is
|
|
811
|
-
* a non-empty tuple (a plain non-empty tuple or a branded `NonEmptyArray`,
|
|
812
|
-
* both of which extend `NonEmptyTuple<unknown>`).
|
|
813
|
-
*/
|
|
814
|
-
type ConcatResult<
|
|
815
|
-
Ar1 extends readonly unknown[],
|
|
816
|
-
Ar2 extends readonly unknown[],
|
|
817
|
-
> =
|
|
818
|
-
Ar1 extends NonEmptyTuple<unknown>
|
|
819
|
-
? readonly [...Ar1, ...Ar2] & NonEmptyArray<Ar1[number] | Ar2[number]>
|
|
820
|
-
: Ar2 extends NonEmptyTuple<unknown>
|
|
821
|
-
? readonly [...Ar1, ...Ar2] & NonEmptyArray<Ar1[number] | Ar2[number]>
|
|
822
|
-
: readonly [...Ar1, ...Ar2];
|
|
823
|
-
|
|
824
732
|
/**
|
|
825
733
|
* Groups elements by a key derived from each element.
|
|
826
734
|
*
|
|
@@ -985,3 +893,95 @@ export const cartesianProduct = <T,>(
|
|
|
985
893
|
|
|
986
894
|
return first.flatMap((item) => restProduct.map((prod) => [item, ...prod]));
|
|
987
895
|
};
|
|
896
|
+
|
|
897
|
+
const scanImpl = <E, S>(
|
|
898
|
+
array: readonly E[],
|
|
899
|
+
reducer: (accumulator: S, currentValue: E, currentIndex: SizeType.Arr) => S,
|
|
900
|
+
init: S,
|
|
901
|
+
): NonEmptyTuple<S> => {
|
|
902
|
+
const mut_result = castMutable<NonEmptyTuple<S>>(
|
|
903
|
+
newArray<PositiveUint32, S>(asPositiveUint32(array.length + 1), init),
|
|
904
|
+
);
|
|
905
|
+
|
|
906
|
+
let mut_acc = init;
|
|
907
|
+
|
|
908
|
+
for (const [index, value] of array.entries()) {
|
|
909
|
+
mut_acc = reducer(mut_acc, value, asUint32(index));
|
|
910
|
+
|
|
911
|
+
mut_result[index + 1] = mut_acc;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
return mut_result;
|
|
915
|
+
};
|
|
916
|
+
|
|
917
|
+
/** The result of sorting `Ar`: same elements, same length, same bounds. */
|
|
918
|
+
type SortedResult<Ar extends readonly unknown[]> =
|
|
919
|
+
HasLengthConstraint<Ar> extends true
|
|
920
|
+
? ChangeArrayElement<Ar, Ar[number]>
|
|
921
|
+
: IsFixedLengthList<Ar> extends true
|
|
922
|
+
? FixedLengthTuple<Ar['length'], Ar[number]>
|
|
923
|
+
: Ar extends NonEmptyTuple<unknown>
|
|
924
|
+
? NonEmptyArray<Ar[number]>
|
|
925
|
+
: readonly Ar[number][];
|
|
926
|
+
|
|
927
|
+
const filterImpl = <E,>(
|
|
928
|
+
array: readonly E[],
|
|
929
|
+
predicate: (a: E, index: SizeType.Arr) => boolean,
|
|
930
|
+
): readonly E[] => array.filter((a, i) => predicate(a, asUint32(i)));
|
|
931
|
+
|
|
932
|
+
const filterNotImpl = <E,>(
|
|
933
|
+
array: readonly E[],
|
|
934
|
+
predicate: (a: E, index: SizeType.Arr) => boolean,
|
|
935
|
+
): readonly E[] => array.filter((a, i) => !predicate(a, asUint32(i)));
|
|
936
|
+
|
|
937
|
+
const flatImpl = (
|
|
938
|
+
array: readonly unknown[],
|
|
939
|
+
depth?: SafeUintWithSmallInt,
|
|
940
|
+
): readonly unknown[] => array.flat(depth);
|
|
941
|
+
|
|
942
|
+
/**
|
|
943
|
+
* Element type of {@link partition}'s result: a chunk holds between 1 and `N`
|
|
944
|
+
* elements. The lower bound is what makes this worth spelling out — `partition`
|
|
945
|
+
* never emits an empty chunk, so indexed access into a chunk is not `undefined`
|
|
946
|
+
* at position `0`, unlike with a plain `readonly E[]`.
|
|
947
|
+
*
|
|
948
|
+
* Falls back to {@link NonEmptyArray} when `N` is not a bound the brand can
|
|
949
|
+
* express, which keeps that lower bound in every case.
|
|
950
|
+
*/
|
|
951
|
+
type PartitionChunk<N, E> = N extends SupportedLength
|
|
952
|
+
? BoundedLengthArray<1, N, E>
|
|
953
|
+
: NonEmptyArray<E>;
|
|
954
|
+
|
|
955
|
+
const partitionImpl = <E, N extends WithSmallInt<PositiveInt & SizeType.Arr>>(
|
|
956
|
+
array: readonly E[],
|
|
957
|
+
chunkSize: N,
|
|
958
|
+
): readonly (readonly E[])[] =>
|
|
959
|
+
chunkSize < 2
|
|
960
|
+
? ([] as const)
|
|
961
|
+
: // eslint-disable-next-line total-functions/no-partial-division
|
|
962
|
+
seq(asUint32(Math.ceil(array.length / chunkSize))).map((i: Uint32) =>
|
|
963
|
+
array.slice(chunkSize * i, chunkSize * (i + 1)),
|
|
964
|
+
);
|
|
965
|
+
|
|
966
|
+
/**
|
|
967
|
+
* Alias for `partition`.
|
|
968
|
+
*
|
|
969
|
+
* @see {@link partition}
|
|
970
|
+
*/
|
|
971
|
+
export const chunk = partition;
|
|
972
|
+
|
|
973
|
+
/**
|
|
974
|
+
* Return type of {@link concat}: the concatenated tuple `readonly [...Ar1,
|
|
975
|
+
* ...Ar2]`, additionally branded as {@link NonEmptyArray} when either input is
|
|
976
|
+
* a non-empty tuple (a plain non-empty tuple or a branded `NonEmptyArray`, both
|
|
977
|
+
* of which extend `NonEmptyTuple<unknown>`).
|
|
978
|
+
*/
|
|
979
|
+
type ConcatResult<
|
|
980
|
+
Ar1 extends readonly unknown[],
|
|
981
|
+
Ar2 extends readonly unknown[],
|
|
982
|
+
> =
|
|
983
|
+
Ar1 extends NonEmptyTuple<unknown>
|
|
984
|
+
? readonly [...Ar1, ...Ar2] & NonEmptyArray<Ar1[number] | Ar2[number]>
|
|
985
|
+
: Ar2 extends NonEmptyTuple<unknown>
|
|
986
|
+
? readonly [...Ar1, ...Ar2] & NonEmptyArray<Ar1[number] | Ar2[number]>
|
|
987
|
+
: readonly [...Ar1, ...Ar2];
|
|
@@ -71,8 +71,8 @@ describe('Arr transformations', () => {
|
|
|
71
71
|
|
|
72
72
|
test('should preserve the tuple shape under a generic parameter', () => {
|
|
73
73
|
// A caller that is itself generic over the tuple cannot resolve a
|
|
74
|
-
// conditional return type, so `map` has to report the homomorphic
|
|
75
|
-
//
|
|
74
|
+
// conditional return type, so `map` has to report the homomorphic mapping
|
|
75
|
+
// directly for a parameter that carries no length brand.
|
|
76
76
|
const mapValues = <const T extends readonly Readonly<{ v: unknown }>[]>(
|
|
77
77
|
boxes: T,
|
|
78
78
|
): Readonly<{ [K in keyof T]: unknown }> => map(boxes, (b) => b.v);
|
|
@@ -63,11 +63,11 @@ type Cast<A, B> = A extends B ? A : never;
|
|
|
63
63
|
*/
|
|
64
64
|
// Type guard overloads - narrow the entire array type.
|
|
65
65
|
//
|
|
66
|
-
// Both narrowed types are intersected with `Ar`: a type predicate's type has
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
//
|
|
70
|
-
//
|
|
66
|
+
// Both narrowed types are intersected with `Ar`: a type predicate's type has to
|
|
67
|
+
// be assignable to the parameter's type, and neither the deferred conditional
|
|
68
|
+
// `ChangeArrayElement<Ar, S>` nor the mapped type over a generic `Ar` is
|
|
69
|
+
// (TS2677). The intersection also keeps whatever the caller already knew about
|
|
70
|
+
// the array — a branded five-tuple stays a five-tuple.
|
|
71
71
|
export function every<
|
|
72
72
|
const Ar extends readonly unknown[] & UnknownBrand,
|
|
73
73
|
S extends Ar[number],
|
|
@@ -76,8 +76,8 @@ export function every<
|
|
|
76
76
|
predicate: (a: Ar[number], index: ArrayIndex<Ar>) => a is S,
|
|
77
77
|
): array is ChangeArrayElement<Ar, S> & Ar;
|
|
78
78
|
|
|
79
|
-
// A plain array or tuple carries no length brand, so the homomorphic mapping
|
|
80
|
-
//
|
|
79
|
+
// A plain array or tuple carries no length brand, so the homomorphic mapping is
|
|
80
|
+
// the whole answer — same reasoning as in `map`.
|
|
81
81
|
export function every<
|
|
82
82
|
const Ar extends readonly unknown[],
|
|
83
83
|
S extends Ar[number],
|
|
@@ -98,8 +98,8 @@ export function every<const Ar extends readonly unknown[]>(
|
|
|
98
98
|
// returned function*, not two overloads of `every` itself: both curried
|
|
99
99
|
// signatures take the same single predicate, so overload resolution would
|
|
100
100
|
// always pick the first and the second would be dead — which is what left a
|
|
101
|
-
// plain `readonly unknown[]` unable to satisfy the `UnknownBrand` constraint
|
|
102
|
-
//
|
|
101
|
+
// plain `readonly unknown[]` unable to satisfy the `UnknownBrand` constraint at
|
|
102
|
+
// the call site of the returned guard.
|
|
103
103
|
//
|
|
104
104
|
// The intersection is also what keeps the group compatible with the
|
|
105
105
|
// implementation signature. A lone `<Ar extends readonly E[] & UnknownBrand>`
|
|
@@ -136,11 +136,6 @@ export function every<E>(
|
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
const everyImpl = <E,>(
|
|
140
|
-
array: readonly E[],
|
|
141
|
-
predicate: (a: E, index: SizeType.Arr) => boolean,
|
|
142
|
-
): boolean => array.every((a, i) => predicate(a, asUint32(i)));
|
|
143
|
-
|
|
144
139
|
/**
|
|
145
140
|
* Tests whether at least one element in an array passes a test implemented by a predicate.
|
|
146
141
|
*
|
|
@@ -186,11 +181,6 @@ export function some<E>(
|
|
|
186
181
|
}
|
|
187
182
|
}
|
|
188
183
|
|
|
189
|
-
const someImpl = <E,>(
|
|
190
|
-
array: readonly E[],
|
|
191
|
-
predicate: (a: E, index: SizeType.Arr) => boolean,
|
|
192
|
-
): boolean => array.some((a, i) => predicate(a, asUint32(i)));
|
|
193
|
-
|
|
194
184
|
/**
|
|
195
185
|
* Checks if an index is within the valid range of an array.
|
|
196
186
|
*
|
|
@@ -212,3 +202,13 @@ export const indexIsInRange = <E,>(
|
|
|
212
202
|
array: readonly E[],
|
|
213
203
|
index: SizeType.ArgArr,
|
|
214
204
|
): boolean => Num.isInRange(0, array.length)(index);
|
|
205
|
+
|
|
206
|
+
const everyImpl = <E,>(
|
|
207
|
+
array: readonly E[],
|
|
208
|
+
predicate: (a: E, index: SizeType.Arr) => boolean,
|
|
209
|
+
): boolean => array.every((a, i) => predicate(a, asUint32(i)));
|
|
210
|
+
|
|
211
|
+
const someImpl = <E,>(
|
|
212
|
+
array: readonly E[],
|
|
213
|
+
predicate: (a: E, index: SizeType.Arr) => boolean,
|
|
214
|
+
): boolean => array.some((a, i) => predicate(a, asUint32(i)));
|