array.ts raw
1 /* eslint-disable @typescript-eslint/no-explicit-any */
2 declare global {
3 interface Array<T> {
4 /**
5 * Sorts the array by the provided property and returns a new sorted array.
6 * Default sorting is ASC. You can apply DESC sorting by using the optional parameter "order = 'desc'"
7 */
8 sortBy<K>(keyFunction: (t: T) => K, order?: 'asc' | 'desc'): T[];
9
10 /** Check if the array is empty. */
11 empty(): boolean;
12
13 groupBy<K, R>(
14 keyFunction: (t: T) => K,
15 reduceFn: (items: T[]) => R
16 ): Map<K, R>;
17 }
18 }
19
20 if (!Array.prototype.empty) {
21 Array.prototype.empty = function (): boolean {
22 return this.length === 0;
23 };
24 }
25
26 if (!Array.prototype.sortBy) {
27 Array.prototype.sortBy = function <T, K>(
28 keyFunction: (t: T) => K,
29 order?: string
30 ): T[] {
31 if (this.length === 0) {
32 return [];
33 }
34
35 // determine sort order (asc or desc / asc is default)
36 let asc = true;
37 if (order === 'desc') {
38 asc = false;
39 }
40
41 const arrayClone = Array.from(this) as any[];
42 const firstSortProperty = keyFunction(arrayClone[0]);
43
44 if (typeof firstSortProperty === 'string') {
45 // string in-place sort
46 arrayClone.sort((a, b) => {
47 if (asc) {
48 return ('' + (keyFunction(a) as unknown as string)).localeCompare(
49 keyFunction(b) as unknown as string
50 );
51 }
52
53 return ('' + (keyFunction(b) as unknown as string)).localeCompare(
54 keyFunction(a) as unknown as string
55 );
56 });
57 } else if (typeof firstSortProperty === 'number') {
58 // number in-place sort
59 if (asc) {
60 arrayClone.sort(
61 (a, b) => Number(keyFunction(a)) - Number(keyFunction(b))
62 );
63 } else {
64 arrayClone.sort(
65 (a, b) => Number(keyFunction(b)) - Number(keyFunction(a))
66 );
67 }
68 } else {
69 throw new Error('sortBy is not implemented for that type!');
70 }
71
72 return arrayClone;
73 };
74 }
75
76 if (!Array.prototype.groupBy) {
77 Array.prototype.groupBy = function <T>(
78 fn: (item: T) => any,
79 reduceFn: (items: T[]) => any
80 ): Map<any, any> {
81 const result = new Map<any, any>();
82
83 const distinctKeys = new Set<any>(this.map((x) => fn(x)));
84
85 for (const distinctKey of distinctKeys) {
86 const distinctKeyItems = this.filter((x) => fn(x) === distinctKey);
87
88 result.set(distinctKey, reduceFn(distinctKeyItems));
89 }
90
91 return result;
92 };
93 }
94
95 export {};
96