UNPKG

1.84 kBPlain TextView Raw
1/** A typical comparator for sorting object keys */
2type KeyComparator = (a: string, b: string) => number
3
4/** An indexable object */
5type IndexedObject = { [key: string]: any }
6
7/**
8 * Returns a copy of the passed array, with all nested objects within it sorted deeply by their keys, without mangling any nested arrays.
9 * @param subject The unsorted array.
10 * @param comparator An optional comparator for sorting keys of objects.
11 * @returns The new sorted array.
12 */
13export function sortArray<T extends any[]>(
14 subject: T,
15 comparator?: KeyComparator
16): T {
17 const result = []
18 for (let value of subject) {
19 // Recurse if object or array
20 if (value != null) {
21 if (Array.isArray(value)) {
22 value = sortArray(value, comparator)
23 } else if (typeof value === 'object') {
24 /* eslint no-use-before-define:0 */
25 value = sortObject(value, comparator)
26 }
27 }
28
29 // Push
30 result.push(value)
31 }
32 return result as T
33}
34
35/**
36 * Returns a copy of the passed object, with all nested objects within it sorted deeply by their keys, without mangling any nested arrays inside of it.
37 * @param subject The unsorted object.
38 * @param comparator An optional comparator for sorting keys of objects.
39 * @returns The new sorted object.
40 */
41export default function sortObject<T extends IndexedObject>(
42 subject: T,
43 comparator?: KeyComparator
44): T {
45 const result: IndexedObject = {} as T
46 const sortedKeys = Object.keys(subject).sort(comparator)
47 for (let i = 0; i < sortedKeys.length; ++i) {
48 // Fetch
49 const key = sortedKeys[i]
50 let value = subject[key]
51
52 // Recurse if object or array
53 if (value != null) {
54 if (Array.isArray(value)) {
55 value = sortArray(value, comparator)
56 } else if (typeof value === 'object') {
57 value = sortObject(value, comparator)
58 }
59 }
60
61 // Push
62 result[key] = value
63 }
64 return result as T
65}