@planet-matrix/mobius-model 0.3.0 → 0.4.0

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.
Files changed (82) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +4 -1
  3. package/dist/index.js +4 -2
  4. package/dist/index.js.map +18 -3
  5. package/package.json +3 -3
  6. package/scripts/build.ts +4 -4
  7. package/src/basic/README.md +143 -0
  8. package/src/basic/array.ts +872 -0
  9. package/src/basic/bigint.ts +114 -0
  10. package/src/basic/boolean.ts +180 -0
  11. package/src/basic/error.ts +51 -0
  12. package/src/basic/function.ts +453 -0
  13. package/src/basic/helper.ts +276 -0
  14. package/src/basic/index.ts +15 -0
  15. package/src/basic/is.ts +320 -0
  16. package/src/basic/number.ts +178 -0
  17. package/src/basic/object.ts +58 -0
  18. package/src/basic/promise.ts +464 -0
  19. package/src/basic/regexp.ts +7 -0
  20. package/src/basic/stream.ts +140 -0
  21. package/src/basic/string.ts +308 -0
  22. package/src/basic/symbol.ts +164 -0
  23. package/src/basic/temporal.ts +224 -0
  24. package/src/index.ts +2 -0
  25. package/src/type/README.md +330 -0
  26. package/src/type/array.ts +5 -0
  27. package/src/type/boolean.ts +471 -0
  28. package/src/type/class.ts +419 -0
  29. package/src/type/function.ts +1519 -0
  30. package/src/type/helper.ts +135 -0
  31. package/src/type/index.ts +14 -0
  32. package/src/type/intersection.ts +93 -0
  33. package/src/type/is.ts +247 -0
  34. package/src/type/iteration.ts +233 -0
  35. package/src/type/number.ts +732 -0
  36. package/src/type/object.ts +788 -0
  37. package/src/type/path.ts +73 -0
  38. package/src/type/string.ts +1004 -0
  39. package/src/type/tuple.ts +2424 -0
  40. package/src/type/union.ts +108 -0
  41. package/tests/unit/basic/array.spec.ts +290 -0
  42. package/tests/unit/basic/bigint.spec.ts +50 -0
  43. package/tests/unit/basic/boolean.spec.ts +74 -0
  44. package/tests/unit/basic/error.spec.ts +32 -0
  45. package/tests/unit/basic/function.spec.ts +175 -0
  46. package/tests/unit/basic/helper.spec.ts +118 -0
  47. package/tests/unit/basic/number.spec.ts +74 -0
  48. package/tests/unit/basic/object.spec.ts +15 -0
  49. package/tests/unit/basic/promise.spec.ts +232 -0
  50. package/tests/unit/basic/regexp.spec.ts +11 -0
  51. package/tests/unit/basic/stream.spec.ts +120 -0
  52. package/tests/unit/basic/string.spec.ts +74 -0
  53. package/tests/unit/basic/symbol.spec.ts +72 -0
  54. package/tests/unit/basic/temporal.spec.ts +78 -0
  55. package/dist/index.d.ts +0 -2
  56. package/dist/index.d.ts.map +0 -1
  57. package/dist/reactor/index.d.ts +0 -3
  58. package/dist/reactor/index.d.ts.map +0 -1
  59. package/dist/reactor/reactor-core/flags.d.ts +0 -99
  60. package/dist/reactor/reactor-core/flags.d.ts.map +0 -1
  61. package/dist/reactor/reactor-core/index.d.ts +0 -4
  62. package/dist/reactor/reactor-core/index.d.ts.map +0 -1
  63. package/dist/reactor/reactor-core/primitive.d.ts +0 -276
  64. package/dist/reactor/reactor-core/primitive.d.ts.map +0 -1
  65. package/dist/reactor/reactor-core/reactive-system.d.ts +0 -241
  66. package/dist/reactor/reactor-core/reactive-system.d.ts.map +0 -1
  67. package/dist/reactor/reactor-operators/branch.d.ts +0 -19
  68. package/dist/reactor/reactor-operators/branch.d.ts.map +0 -1
  69. package/dist/reactor/reactor-operators/convert.d.ts +0 -30
  70. package/dist/reactor/reactor-operators/convert.d.ts.map +0 -1
  71. package/dist/reactor/reactor-operators/create.d.ts +0 -26
  72. package/dist/reactor/reactor-operators/create.d.ts.map +0 -1
  73. package/dist/reactor/reactor-operators/filter.d.ts +0 -269
  74. package/dist/reactor/reactor-operators/filter.d.ts.map +0 -1
  75. package/dist/reactor/reactor-operators/index.d.ts +0 -8
  76. package/dist/reactor/reactor-operators/index.d.ts.map +0 -1
  77. package/dist/reactor/reactor-operators/join.d.ts +0 -48
  78. package/dist/reactor/reactor-operators/join.d.ts.map +0 -1
  79. package/dist/reactor/reactor-operators/map.d.ts +0 -165
  80. package/dist/reactor/reactor-operators/map.d.ts.map +0 -1
  81. package/dist/reactor/reactor-operators/utility.d.ts +0 -48
  82. package/dist/reactor/reactor-operators/utility.d.ts.map +0 -1
@@ -0,0 +1,872 @@
1
+ /**
2
+ * Convert an iterable target into an array using spread.
3
+ *
4
+ * @example
5
+ * ```
6
+ * // Expect: [1, 2, 3]
7
+ * const example1 = arrayFromSpread(new Set([1, 2, 3]))
8
+ * // Expect: []
9
+ * const example2 = arrayFromSpread([])
10
+ * ```
11
+ */
12
+ export const arrayFromSpread = <T = unknown>(target: Iterable<T>): T[] => {
13
+ return [...target]
14
+ }
15
+
16
+ /**
17
+ * Returns the length of `targetArray`.
18
+ *
19
+ * @example
20
+ * ```
21
+ * // Expect: 3
22
+ * const example1 = arrayLength(["a", "b", "c"])
23
+ * // Expect: 0
24
+ * const example2 = arrayLength([])
25
+ * ```
26
+ */
27
+ export const arrayLength = (targetArray: unknown[]): number => {
28
+ return targetArray.length
29
+ }
30
+
31
+ /**
32
+ * Returns a copy of `targetArray` in which last element has been removed.
33
+ * New array's length is `targetArray.length - 1`.
34
+ *
35
+ * @example
36
+ * ```
37
+ * // Expect: [1, 2]
38
+ * const example1 = arrayPop([1, 2, 3])
39
+ * // Expect: []
40
+ * const example2 = arrayPop(["only"])
41
+ * ```
42
+ */
43
+ export const arrayPop = <T = unknown>(targetArray: T[]): T[] => {
44
+ return targetArray.slice(0, -1)
45
+ }
46
+
47
+ /**
48
+ * Returns a copy of `targetArray` in which inserts the given `item` as new last item.
49
+ * New array's length is `targetArray.length + 1`.
50
+ *
51
+ * @example
52
+ * ```
53
+ * // Expect: [1, 2, 3]
54
+ * const example1 = arrayPush(3, [1, 2])
55
+ * // Expect: ["a"]
56
+ * const example2 = arrayPush("a", [])
57
+ * ```
58
+ */
59
+ export const arrayPush = <T = unknown>(item: T, targetArray: T[]): T[] => {
60
+ return [...targetArray, item]
61
+ }
62
+
63
+ /**
64
+ * Alias of {@link arrayPush}.
65
+ *
66
+ * @example
67
+ * ```
68
+ * // Expect: [1, 2]
69
+ * const example1 = arrayAppend(2, [1])
70
+ * // Expect: ["x"]
71
+ * const example2 = arrayAppend("x", [])
72
+ * ```
73
+ */
74
+ export const arrayAppend: typeof arrayPush = arrayPush
75
+
76
+ /**
77
+ * Returns a copy of `targetArray` in which inserts the given `item` as new fist item.
78
+ * New array's length is `targetArray`'s length + 1.
79
+ *
80
+ * @example
81
+ * ```
82
+ * // Expect: [0, 1, 2]
83
+ * const example1 = arrayUnshift(0, [1, 2])
84
+ * // Expect: ["a"]
85
+ * const example2 = arrayUnshift("a", [])
86
+ * ```
87
+ */
88
+ export const arrayUnshift = <T = unknown>(item: T, targetArray: T[]): T[] => {
89
+ return [item, ...targetArray]
90
+ }
91
+
92
+ /**
93
+ * Alias of {@link arrayUnshift}.
94
+ *
95
+ * @example
96
+ * ```
97
+ * // Expect: ["first", "second"]
98
+ * const example1 = arrayPrepend("first", ["second"])
99
+ * // Expect: [true]
100
+ * const example2 = arrayPrepend(true, [])
101
+ * ```
102
+ */
103
+ export const arrayPrepend: typeof arrayUnshift = arrayUnshift
104
+
105
+ /**
106
+ * Returns a copy of `targetArray` in which first element has been removed.
107
+ * New array's length is `targetArray`'s length - 1.
108
+ *
109
+ * @example
110
+ * ```
111
+ * // Expect: [2, 3]
112
+ * const example1 = arrayShift([1, 2, 3])
113
+ * // Expect: []
114
+ * const example2 = arrayShift(["only"])
115
+ * ```
116
+ */
117
+ export const arrayShift = <T = unknown>(targetArray: T[]): T[] => {
118
+ return targetArray.slice(1)
119
+ }
120
+
121
+ /**
122
+ * Returns the first element of `targetArray`.
123
+ *
124
+ * @example
125
+ * ```
126
+ * // Expect: 1
127
+ * const example1 = arrayHead([1, 2, 3])
128
+ * // Expect: undefined
129
+ * const example2 = arrayHead([])
130
+ * ```
131
+ *
132
+ * @see {@link arrayTail}, {@link arrayLast}
133
+ */
134
+ export const arrayHead = <T = unknown>(targetArray: T[]): T | undefined => {
135
+ return targetArray[0]
136
+ }
137
+
138
+ /**
139
+ * Returns the tail of `targetArray`.
140
+ *
141
+ * @example
142
+ * ```
143
+ * // Expect: [2, 3]
144
+ * const example1 = arrayTail([1, 2, 3])
145
+ * // Expect: []
146
+ * const example2 = arrayTail(["only"])
147
+ * ```
148
+ *
149
+ * @see {@link arrayHead}, {@link arrayInit}
150
+ */
151
+ export const arrayTail = <T = unknown>(targetArray: T[]): T[] => {
152
+ return targetArray.slice(1)
153
+ }
154
+
155
+ /**
156
+ * Returns the init of `targetArray`.
157
+ *
158
+ * @example
159
+ * ```
160
+ * // Expect: [1, 2]
161
+ * const example1 = arrayInit([1, 2, 3])
162
+ * // Expect: []
163
+ * const example2 = arrayInit(["only"])
164
+ * ```
165
+ *
166
+ * @see {@link arrayLast}, {@link arrayTail}
167
+ */
168
+ export const arrayInit = <T = unknown>(targetArray: T[]): T[] => {
169
+ return targetArray.slice(0, -1)
170
+ }
171
+
172
+ /**
173
+ * Returns the last element of `targetArray`.
174
+ *
175
+ * @example
176
+ * ```
177
+ * // Expect: 3
178
+ * const example1 = arrayLast([1, 2, 3])
179
+ * // Expect: undefined
180
+ * const example2 = arrayLast([])
181
+ * ```
182
+ *
183
+ * @see {@link arrayInit}, {@link arrayHead}
184
+ */
185
+ export const arrayLast = <T = unknown>(targetArray: T[]): T | undefined => {
186
+ return targetArray.at(-1)
187
+ }
188
+
189
+ /**
190
+ * Returns a copy of a section of an array.
191
+ *
192
+ * @example
193
+ * ```
194
+ * // Expect: ["b", "c"]
195
+ * const example1 = arraySlice(1, 3, ["a", "b", "c", "d"])
196
+ * // Expect: []
197
+ * const example2 = arraySlice(2, 2, [1, 2, 3])
198
+ * ```
199
+ *
200
+ * @see {@link arraySliceInit}, {@link arraySliceTail}
201
+ */
202
+ export const arraySlice = <T = unknown>(
203
+ start: number,
204
+ end: number,
205
+ targetArray: T[],
206
+ ): T[] => {
207
+ return targetArray.slice(start, end)
208
+ }
209
+
210
+ /**
211
+ * Returns a copy of a section of an array.
212
+ *
213
+ * @example
214
+ * ```
215
+ * // Expect: [3, 4]
216
+ * const example1 = arraySliceTail(2, [1, 2, 3, 4])
217
+ * // Expect: []
218
+ * const example2 = arraySliceTail(1, ["only"])
219
+ * ```
220
+ *
221
+ * @see {@link arraySlice}, {@link arraySliceTail}
222
+ * @see {@link arrayDrop}
223
+ */
224
+ export const arraySliceTail = <T = unknown>(
225
+ start: number,
226
+ targetArray: T[],
227
+ ): T[] => {
228
+ return targetArray.slice(start)
229
+ }
230
+
231
+ /**
232
+ * Returns a copy of a section of an array.
233
+ *
234
+ * @example
235
+ * ```
236
+ * // Expect: [3, 4]
237
+ * const example1 = arrayDrop(2, [1, 2, 3, 4])
238
+ * // Expect: []
239
+ * const example2 = arrayDrop(-2, [1, 2])
240
+ * ```
241
+ *
242
+ * @see {@link arraySliceTail}
243
+ */
244
+ export const arrayDrop = <T = unknown>(
245
+ n: number,
246
+ targetArray: T[],
247
+ ): T[] => {
248
+ return targetArray.slice(Math.abs(Math.round(n)))
249
+ }
250
+ /**
251
+ * Returns a copy of a section of an array.
252
+ *
253
+ * @example
254
+ * ```
255
+ * // Expect: [1, 2]
256
+ * const example1 = arraySliceInit(2, [1, 2, 3, 4])
257
+ * // Expect: []
258
+ * const example2 = arraySliceInit(0, [1, 2])
259
+ * ```
260
+ *
261
+ * @see {@link arraySlice}, {@link arraySliceInit}
262
+ */
263
+ export const arraySliceInit = <T = unknown>(
264
+ end: number,
265
+ targetArray: T[],
266
+ ): T[] => {
267
+ return targetArray.slice(0, Math.round(end))
268
+ }
269
+
270
+ /**
271
+ * Returns a copy of a section of an array.
272
+ *
273
+ * @example
274
+ * ```
275
+ * // Expect: [1, 2]
276
+ * const example1 = arrayDropLast(2, [1, 2, 3, 4])
277
+ * // Expect: []
278
+ * const example2 = arrayDropLast(3, [1, 2])
279
+ * ```
280
+ *
281
+ * @see {@link arraySliceInit}
282
+ */
283
+ export const arrayDropLast = <T = unknown>(
284
+ n: number,
285
+ targetArray: T[],
286
+ ): T[] => {
287
+ return targetArray.slice(0, -Math.abs(Math.round(n)))
288
+ }
289
+
290
+ /**
291
+ * Returns a copy of `targetArray` with the elements between `start` (inclusive)
292
+ * and `end` (exclusive) removed.
293
+ *
294
+ * @example
295
+ * ```
296
+ * // Expect: ["a", "d"]
297
+ * const example1 = arrayRemove(1, 3, ["a", "b", "c", "d"])
298
+ * // Expect: [1, 2, 3]
299
+ * const example2 = arrayRemove(2, 2, [1, 2, 3])
300
+ * ```
301
+ */
302
+ export const arrayRemove = <T = unknown>(
303
+ start: number, end: number, targetArray: T[]
304
+ ): T[] => {
305
+ let internalStart = Math.abs(Math.round(start))
306
+ let internalEnd = Math.abs(Math.round(end))
307
+
308
+ if (internalEnd < internalStart) {
309
+ [internalStart, internalEnd] = [internalEnd, internalStart]
310
+ }
311
+ return [...targetArray.slice(0, internalStart), ...targetArray.slice(internalEnd)]
312
+ }
313
+
314
+ /**
315
+ * Returns a copy of `targetArray` with the element at `index` removed.
316
+ *
317
+ * @example
318
+ * ```
319
+ * // Expect: ["a", "c"]
320
+ * const example1 = arrayRemoveIndex(1, ["a", "b", "c"])
321
+ * // Expect: []
322
+ * const example2 = arrayRemoveIndex(0, ["only"])
323
+ * ```
324
+ */
325
+ export const arrayRemoveIndex = <T = unknown>(
326
+ index: number,
327
+ targetArray: T[],
328
+ ): T[] => {
329
+ return [...targetArray.slice(0, index), ...targetArray.slice(index + 1 === 0 ? Infinity : index + 1)]
330
+ }
331
+
332
+ /**
333
+ * Combines two array. `appendedArray` will be appended to the end of `targetArray`.
334
+ *
335
+ * @example
336
+ * ```
337
+ * // Expect: [1, 2, 3, 4]
338
+ * const example1 = arrayConcat([3, 4], [1, 2])
339
+ * // Expect: ["a"]
340
+ * const example2 = arrayConcat([], ["a"])
341
+ * ```
342
+ */
343
+ export const arrayConcat = <T = unknown>(appendedArray: T[], targetArray: T[]): T[] => {
344
+ return [...targetArray, ...appendedArray]
345
+ }
346
+
347
+ /**
348
+ * Adds all the elements of an array into a string, separated by the specified
349
+ * separator string.
350
+ *
351
+ * @example
352
+ * ```
353
+ * // Expect: "a,b,c"
354
+ * const example1 = arrayJoin(",", ["a", "b", "c"])
355
+ * // Expect: ""
356
+ * const example2 = arrayJoin("-", [])
357
+ * ```
358
+ */
359
+ export const arrayJoin = (separator: string, targetArray: unknown[]): string => {
360
+ return targetArray.join(separator)
361
+ }
362
+
363
+ /**
364
+ * Returns the first index at which a given element can be found in the array,
365
+ * or -1 if it is not present.
366
+ *
367
+ * @example
368
+ * ```
369
+ * // Expect: 1
370
+ * const example1 = arrayIndexOf("b", ["a", "b", "c"])
371
+ * // Expect: -1
372
+ * const example2 = arrayIndexOf(9, [1, 2, 3])
373
+ * ```
374
+ */
375
+ export const arrayIndexOf = (searchElement: unknown, targetArray: unknown[]): number => {
376
+ return targetArray.indexOf(searchElement)
377
+ }
378
+
379
+ /**
380
+ * Returns the last index at which a given element can be found in the array,
381
+ * or -1 if it is not present.
382
+ *
383
+ * @example
384
+ * ```
385
+ * // Expect: 2
386
+ * const example1 = arrayLastIndexOf("a", ["a", "b", "a"])
387
+ * // Expect: -1
388
+ * const example2 = arrayLastIndexOf(9, [1, 2, 3])
389
+ * ```
390
+ */
391
+ export const arrayLastIndexOf = (searchElement: unknown, targetArray: unknown[]): number => {
392
+ return targetArray.lastIndexOf(searchElement)
393
+ }
394
+
395
+ /**
396
+ * Predicate whether the target array includes the searchElement.
397
+ *
398
+ * @example
399
+ * ```
400
+ * // Expect: true
401
+ * const example1 = arrayIncludes(2, [1, 2, 3])
402
+ * // Expect: false
403
+ * const example2 = arrayIncludes("x", ["a", "b"])
404
+ * ```
405
+ */
406
+ export const arrayIncludes = <T = unknown>(searchElement: T, targetArray: T[]): boolean => {
407
+ return targetArray.includes(searchElement)
408
+ }
409
+
410
+ /**
411
+ * Predicate whether all elements in the target array satisfy the provided testing function.
412
+ *
413
+ * @example
414
+ * ```
415
+ * // Expect: true
416
+ * const example1 = arrayEvery((item) => item > 0, [1, 2, 3])
417
+ * // Expect: false
418
+ * const example2 = arrayEvery((item) => item > 1, [1, 2, 3])
419
+ * ```
420
+ */
421
+ export function arrayEvery<T = unknown, S extends T = T>(
422
+ predicate: (item: T, index: number, array: T[]) => item is S, targetArray: T[]
423
+ ): targetArray is S[]
424
+ export function arrayEvery<T = unknown>(
425
+ predicate: (item: T, index: number, array: T[]) => boolean, targetArray: T[]
426
+ ): boolean
427
+ export function arrayEvery<T = unknown>(
428
+ predicate: (item: T, index: number, array: T[]) => boolean,
429
+ targetArray: T[],
430
+ ): boolean {
431
+ return targetArray.every((item, index, array) => predicate(item, index, array))
432
+ }
433
+
434
+ /**
435
+ * Alias of {@link arrayEvery}.
436
+ *
437
+ * @example
438
+ * ```
439
+ * // Expect: true
440
+ * const example1 = arrayAll((item) => item !== null, [1, 2])
441
+ * // Expect: false
442
+ * const example2 = arrayAll((item) => item === 0, [0, 1])
443
+ * ```
444
+ */
445
+ export const arrayAll: typeof arrayEvery = arrayEvery
446
+
447
+ /**
448
+ * Predicate whether at least one element in the target array satisfies the provided testing function.
449
+ *
450
+ * @example
451
+ * ```
452
+ * // Expect: true
453
+ * const example1 = arraySome((item) => item > 2, [1, 2, 3])
454
+ * // Expect: false
455
+ * const example2 = arraySome((item) => item < 0, [1, 2, 3])
456
+ * ```
457
+ */
458
+ export const arraySome = <T = unknown>(
459
+ predicate: (item: T, index: number, array: T[]) => boolean,
460
+ targetArray: T[],
461
+ ): boolean => {
462
+ return targetArray.some((item, index, array) => predicate(item, index, array))
463
+ }
464
+
465
+ /**
466
+ * Alias of {@link arraySome}.
467
+ *
468
+ * @example
469
+ * ```
470
+ * // Expect: true
471
+ * const example1 = arrayAny((item) => item === "b", ["a", "b"])
472
+ * // Expect: false
473
+ * const example2 = arrayAny((item) => item === "x", ["a", "b"])
474
+ * ```
475
+ */
476
+ export const arrayAny: typeof arraySome = arraySome
477
+
478
+ /**
479
+ * Applies a function to each element in the target array.
480
+ *
481
+ * @example
482
+ * ```
483
+ * const target: number[] = []
484
+ * arrayForEach((item) => target.push(item * 2), [1, 2, 3])
485
+ * // Expect: [2, 4, 6]
486
+ * const example1 = target
487
+ * ```
488
+ */
489
+ export const arrayForEach = <T = unknown>(
490
+ eachDo: (item: T, index: number, array: T[]) => void,
491
+ targetArray: T[],
492
+ ): void => {
493
+ targetArray.forEach((item, index, array) => {
494
+ eachDo(item, index, array)
495
+ })
496
+ }
497
+
498
+ /**
499
+ * Returns a new array containing all elements of the target array that satisfy the provided testing function.
500
+ *
501
+ * @example
502
+ * ```
503
+ * // Expect: [2, 4]
504
+ * const example1 = arrayFilter((item) => item % 2 === 0, [1, 2, 3, 4])
505
+ * // Expect: []
506
+ * const example2 = arrayFilter((item) => item > 0, [])
507
+ * ```
508
+ *
509
+ * @see {@link arrayReject}
510
+ */
511
+ export function arrayFilter<T = unknown, S extends T = T>(
512
+ predicate: (item: T, index: number, array: T[]) => item is S, targetArray: T[]
513
+ ): S[]
514
+ export function arrayFilter<T = unknown>(
515
+ predicate: (item: T, index: number, array: T[]) => boolean, targetArray: T[]
516
+ ): T[]
517
+ export function arrayFilter<T = unknown>(
518
+ predicate: (item: T, index: number, array: T[]) => boolean,
519
+ targetArray: T[],
520
+ ): T[] {
521
+ return targetArray.filter((item, index, array) => predicate(item, index, array))
522
+ }
523
+
524
+ /**
525
+ * Returns a new array containing all elements of the target array that do not satisfy the provided testing function.
526
+ *
527
+ * @example
528
+ * ```
529
+ * // Expect: [1, 3]
530
+ * const example1 = arrayReject((item) => item % 2 === 0, [1, 2, 3, 4])
531
+ * // Expect: ["a"]
532
+ * const example2 = arrayReject((item) => item === "b", ["a", "b"])
533
+ * ```
534
+ *
535
+ * @see {@link arrayFilter}
536
+ */
537
+ export const arrayReject = <T = unknown>(
538
+ predicate: (item: T, index: number, array: T[]) => boolean,
539
+ targetArray: T[],
540
+ ): T[] => {
541
+ return targetArray.filter((item, index, array) => !predicate(item, index, array))
542
+ }
543
+
544
+ /**
545
+ * Returns a tuple of two arrays: the first array contains the elements of the target array that satisfy the provided testing function, while the second array contains the elements that do not satisfy the testing function.
546
+ *
547
+ * @example
548
+ * ```
549
+ * // Expect: [[2, 4], [1, 3]]
550
+ * const example1 = arrayPartition((item) => item % 2 === 0, [1, 2, 3, 4])
551
+ * // Expect: [[], ["a"]]
552
+ * const example2 = arrayPartition((item) => item === "b", ["a"])
553
+ * ```
554
+ *
555
+ * @see {@link arrayFilter}, {@link arrayReject}
556
+ */
557
+ export const arrayPartition = <T = unknown>(
558
+ predicate: (item: T, index: number, array: T[]) => boolean,
559
+ targetArray: T[],
560
+ ): [T[], T[]] => {
561
+ const truthyArray: T[] = []
562
+ const falsyArray: T[] = []
563
+ targetArray.forEach((item, index, array) => {
564
+ if (predicate(item, index, array)) {
565
+ truthyArray.push(item)
566
+ }
567
+ else {
568
+ falsyArray.push(item)
569
+ }
570
+ })
571
+ return [truthyArray, falsyArray]
572
+ }
573
+
574
+ /**
575
+ * Returns a new array containing the results of applying a provided function to every element in the target array.
576
+ *
577
+ * @example
578
+ * ```
579
+ * // Expect: [2, 4, 6]
580
+ * const example1 = arrayMap((item) => item * 2, [1, 2, 3])
581
+ * // Expect: []
582
+ * const example2 = arrayMap((item) => item, [])
583
+ * ```
584
+ */
585
+ export const arrayMap = <T = unknown, R = unknown>(
586
+ transformation: (item: T, index: number, array: T[]) => R,
587
+ targetArray: T[],
588
+ ): R[] => {
589
+ return targetArray.map((item, index, array) => transformation(item, index, array))
590
+ }
591
+
592
+ /**
593
+ * Returns a new array with all sub-array elements concatenated into it recursively up to the specified depth.
594
+ *
595
+ * @example
596
+ * ```
597
+ * // Expect: [1, 2, 3, 4]
598
+ * const example1 = arrayFlat(1, [1, [2, 3], [4]])
599
+ * // Expect: [1, 2]
600
+ * const example2 = arrayFlat(2, [1, [[2]]])
601
+ * ```
602
+ *
603
+ * @see {@link arrayFlatMap}
604
+ */
605
+ export const arrayFlat = <T = unknown, D extends number = number>(
606
+ depth: D,
607
+ targetArray: T[],
608
+ ): Array<FlatArray<T[], D>> => {
609
+ return targetArray.flat(depth)
610
+ }
611
+
612
+ /**
613
+ * Returns a new array containing the results of applying a provided function to every element in the target array, and then flattening the result by one level.
614
+ *
615
+ * @example
616
+ * ```
617
+ * // Expect: [1, 1, 2, 2]
618
+ * const example1 = arrayFlatMap((item) => [item, item], [1, 2])
619
+ * // Expect: []
620
+ * const example2 = arrayFlatMap((item) => [item], [])
621
+ * ```
622
+ *
623
+ * @see {@link arrayMap}, {@link arrayFlat}
624
+ */
625
+ export const arrayFlatMap = <T = unknown, R = unknown>(
626
+ transformation: (item: T, index: number, array: T[]) => (R | R[]),
627
+ targetArray: T[],
628
+ ): R[] => {
629
+ return targetArray.flatMap((item, index, array) => transformation(item, index, array))
630
+ }
631
+
632
+ /**
633
+ * Returns a single value that is the result of applying a provided function against an accumulator and each element in the target array (from left to right).
634
+ *
635
+ * @example
636
+ * ```
637
+ * // Expect: 6
638
+ * const example1 = arrayReduce((acc, item) => acc + item, 0, [1, 2, 3])
639
+ * // Expect: "abc"
640
+ * const example2 = arrayReduce((acc, item) => acc + item, "", ["a", "b", "c"])
641
+ * ```
642
+ *
643
+ * @see {@link arrayReduceLeft}, {@link arrayReduceRight}
644
+ */
645
+ export const arrayReduce = <T = unknown, R = unknown>(
646
+ reducer: (accumulated: R, item: T, index: number, array: T[]) => R,
647
+ initialValue: R,
648
+ targetArray: T[],
649
+ ): R => {
650
+ return targetArray.reduce((accumulated, item, index, array) => reducer(accumulated, item, index, array), initialValue)
651
+ }
652
+ /**
653
+ * Alias of {@link arrayReduce}.
654
+ *
655
+ * @example
656
+ * ```
657
+ * // Expect: 6
658
+ * const example1 = arrayReduceLeft((acc, item) => acc + item, 0, [1, 2, 3])
659
+ * // Expect: "ab"
660
+ * const example2 = arrayReduceLeft((acc, item) => acc + item, "", ["a", "b"])
661
+ * ```
662
+ *
663
+ * @see {@link arrayReduce}
664
+ */
665
+ export const arrayReduceLeft: typeof arrayReduce = arrayReduce
666
+
667
+ /**
668
+ * Returns a single value that is the result of applying a provided function against an accumulator and each element in the target array (from right to left).
669
+ *
670
+ * @example
671
+ * ```
672
+ * // Expect: "cba"
673
+ * const example1 = arrayReduceRight((acc, item) => acc + item, "", ["a", "b", "c"])
674
+ * // Expect: 6
675
+ * const example2 = arrayReduceRight((acc, item) => acc + item, 0, [1, 2, 3])
676
+ * ```
677
+ *
678
+ * @see {@link arrayReduceLeft}, {@link arrayReduceRight}
679
+ */
680
+ export const arrayReduceRight = <T = unknown, R = unknown>(
681
+ reducer: (accumulated: R, item: T, index: number, array: T[]) => R,
682
+ initialValue: R,
683
+ targetArray: T[],
684
+ ): R => {
685
+ return targetArray.reduceRight((accumulated, item, index, array) => reducer(accumulated, item, index, array), initialValue)
686
+ }
687
+
688
+ /**
689
+ * Returns a new array containing only one copy of each element in the original array.
690
+ *
691
+ * @example
692
+ * ```
693
+ * // Expect: [1, 2, 3]
694
+ * const example1 = arrayUnique([1, 2, 1, 3])
695
+ * // Expect: ["a"]
696
+ * const example2 = arrayUnique(["a", "a"])
697
+ * ```
698
+ */
699
+ export const arrayUnique = <T = unknown>(targetArray: T[]): T[] => {
700
+ return Array.from(new Set(targetArray))
701
+ }
702
+
703
+ /**
704
+ * Returns a new array containing only one copy of each element in the original array,
705
+ * based on the provided unique function.
706
+ *
707
+ * @example
708
+ * ```
709
+ * // Expect: [{ id: 1 }, { id: 2 }]
710
+ * const example1 = arrayUniqueBy((item) => item.id, [{ id: 1 }, { id: 1 }, { id: 2 }])
711
+ * // Expect: []
712
+ * const example2 = arrayUniqueBy((item) => item, [])
713
+ * ```
714
+ */
715
+ export const arrayUniqueBy = <T = unknown>(
716
+ uniqueFunction: (item: T) => unknown, targetArray: T[]
717
+ ): T[] => {
718
+ const uniqueMap = new Map<unknown, T>()
719
+ targetArray.forEach((item) => {
720
+ const uniqueKey = uniqueFunction(item)
721
+ if (!uniqueMap.has(uniqueKey)) {
722
+ uniqueMap.set(uniqueKey, item)
723
+ }
724
+ })
725
+ return Array.from(uniqueMap.values())
726
+ }
727
+
728
+ /**
729
+ * Combines two arrays into one array (no duplicates) composed of the elements of each array.
730
+ *
731
+ * @example
732
+ * ```
733
+ * // Expect: [1, 2, 3]
734
+ * const example1 = arrayUnion([1, 2], [2, 3])
735
+ * // Expect: ["a"]
736
+ * const example2 = arrayUnion(["a"], [])
737
+ * ```
738
+ *
739
+ * @see {@link arrayIntersection}
740
+ */
741
+ export const arrayUnion = <T = unknown>(firstArray: T[], secondArray: T[]): T[] => {
742
+ return arrayUnique([...firstArray, ...secondArray])
743
+ }
744
+
745
+ type CompareArray = (arr1: unknown[], arr2: unknown[]) => unknown[]
746
+ const _longer: CompareArray = (arr1, arr2) => arr1.length > arr2.length ? arr1 : arr2
747
+ const _shorter: CompareArray = (arr1, arr2) => arr1.length > arr2.length ? arr2 : arr1
748
+ /**
749
+ * Combines two arrays into one array (no duplicates) composed of those elements common to both arrays.
750
+ *
751
+ * @example
752
+ * ```
753
+ * // Expect: [2]
754
+ * const example1 = arrayIntersection([1, 2], [2, 3])
755
+ * // Expect: []
756
+ * const example2 = arrayIntersection(["a"], ["b"])
757
+ * ```
758
+ *
759
+ * @see {@link https://ramdajs.com/docs/#intersection}
760
+ * @see {@link arrayUnion}
761
+ */
762
+ export const arrayIntersection = <T = unknown>(firstArray: T[], secondArray: T[]): T[] => {
763
+ // reference: ramda, it is more efficient when the array length gap is large
764
+ const lookupArr = _longer(firstArray, secondArray)
765
+ const filteredArr = _shorter(firstArray, secondArray)
766
+ // oxlint-disable-next-line no-unsafe-type-assertion
767
+ return arrayUnique(filteredArr.filter(item => lookupArr.includes(item))) as T[]
768
+ }
769
+
770
+ /**
771
+ * Returns a new array with the elements in reverse order.
772
+ *
773
+ * @example
774
+ * ```
775
+ * // Expect: [3, 2, 1]
776
+ * const example1 = arrayReverse([1, 2, 3])
777
+ * // Expect: []
778
+ * const example2 = arrayReverse([])
779
+ * ```
780
+ */
781
+ export const arrayReverse = <T = unknown>(targetArray: T[]): T[] => {
782
+ return targetArray.toReversed()
783
+ }
784
+
785
+ /**
786
+ * Returns a new array with the elements sorted according to the provided compare function.
787
+ *
788
+ * @example
789
+ * ```
790
+ * // Expect: [1, 2, 3]
791
+ * const example1 = arraySort((a, b) => a - b, [3, 1, 2])
792
+ * // Expect: ["a", "b"]
793
+ * const example2 = arraySort((a, b) => a.localeCompare(b), ["b", "a"])
794
+ * ```
795
+ */
796
+ export const arraySort = <T = unknown>(
797
+ compareFunction: (a: T, b: T) => number,
798
+ targetArray: T[],
799
+ ): T[] => {
800
+ return targetArray.toSorted(compareFunction)
801
+ }
802
+
803
+ /**
804
+ * Shuffle the target array.
805
+ *
806
+ * @see {@link https://github.com/mqyqingfeng/Blog/issues/51}
807
+ *
808
+ * @example
809
+ * ```
810
+ * const example1 = shuffle([1, 2, 3])
811
+ * const example2 = shuffle(["a", "b"])
812
+ * // Expect: example1.length === 3
813
+ * // Expect: example2.length === 2
814
+ * ```
815
+ */
816
+ export const shuffle = <T = unknown>(target: T[]): T[] => {
817
+ const _target = [...target]
818
+ for (let i = _target.length; i !== 0; i = i - 1) {
819
+ const j = Math.floor(Math.random() * i);
820
+ // @ts-expect-error - ignore the error
821
+ [_target[i - 1], _target[j]] = [_target[j], _target[i - 1]]
822
+ }
823
+ return _target
824
+ }
825
+
826
+ /**
827
+ * Applies a function to the value at the given index of an array,
828
+ * returning a new copy of the array with the element at the given index
829
+ * replaced with the result of the function application.
830
+ *
831
+ * @example
832
+ * ```
833
+ * // Expect: [1, 20, 3]
834
+ * const example1 = arrayAdjust(1, (item) => item * 10, [1, 2, 3])
835
+ * // Expect: ["a"]
836
+ * const example2 = arrayAdjust(0, (item) => item, ["a"])
837
+ * ```
838
+ *
839
+ * @see {@link https://ramdajs.com/docs/#adjust}
840
+ */
841
+ export const arrayAdjust = <T = unknown>(
842
+ index: number,
843
+ transformation: (item: T) => T,
844
+ targetArray: T[],
845
+ ): T[] => {
846
+ const _targetArray = [...targetArray]
847
+ // oxlint-disable-next-line no-unsafe-type-assertion
848
+ _targetArray[index] = transformation(_targetArray[index] as T)
849
+ return _targetArray
850
+ }
851
+
852
+ /**
853
+ * Returns a new copy of the array with the element
854
+ * at the provided index replaced with the given value.
855
+ *
856
+ * @example
857
+ * ```
858
+ * // Expect: [1, 9, 3]
859
+ * const example1 = arrayUpdate(1, 9, [1, 2, 3])
860
+ * // Expect: ["x"]
861
+ * const example2 = arrayUpdate(0, "x", ["a"])
862
+ * ```
863
+ *
864
+ * @see {@link arrayAdjust}
865
+ */
866
+ export const arrayUpdate = <T = unknown>(
867
+ index: number,
868
+ newItem: T,
869
+ targetArray: T[],
870
+ ): T[] => {
871
+ return arrayAdjust(index, () => newItem, targetArray)
872
+ }