The Complete Guide to Sorting Arrays of Objects in Typescript
When we create an application or websites we need to sort array data frequently. And in Typescript we often need to sort arrays with strings, numbers or Booleans. But, there may be also the case when we need to sort more complex arrays of objects and not just the plain values.
Sorting is a great thing and it allows you to quickly find, compare and rank objects in any array based on your condition. Sorting array of objects allows us to order the objects based on one or most of their properties.
Lets take an example. Suppose we have an array of person objects with properties name, age and job. Now, sorting them alphabetically by name would order all the People with similar names together. And similarly, sorting by age from lowest or highest (or vise versa) will order them accordingly.
Here are most common use cases that i have came across for sorting arrays of objects in TypeScript.
- Ordering and Organizing fetched data from an API to be more readable
- Ranking some items to show the most relevant first
- Putting items in alphabetical, numerical, or desired order
- Sorting DOM elements to dynamically update the UI
- Sorting products by price or rating for an ecommerce site
There are other many real world complex objects that you may come across and need sorting. Here is the full guide that covers most basic and most advance techniques for sorting array of objects with Typescript.
Basic Array Sorting in Typescript
As you may know already, the easiest way to sort an array in Typescript is using the built-in .sort() method. This method allows to sort elements of array and mutate the original array.
For example:
let numbers = [5, 3, 2, 4, 1];
numbers.sort();
console.log(numbers); // [1, 2, 3, 4, 5]
.sort() method sorts values as strings by default. This works flawlessly for sorting numbers and strings but can show incorrect results when you try to sort other data types.
You can customize the way of sorting elements by function .sort(). The compare function takes two arguments (a and b) and :
- It will return a negative number if a should come before b
- It will return a positive number if b should come before a
- It will return 0 if a and b are equal
Here is an example to sort numbers from smallest to largest:
let numbers = [5, 3, 2, 4, 1];
numbers.sort((a, b) => a - b);
console.log(numbers); // [1, 2, 3, 4, 5]
The above example passes a compare function that subtracts b from a, and returns a negative number if a is less than b. This compare function gives you a lot of flexibility in how arrays are sorted in Typescript.
Sorting Arrays of Primitives
You can use the sort() method for sorting arrays of primitive values like strings, numbers, and booleans in TypeScript.
Here is an example to sort an array of strings:
let strings = ['c', 'a', 'b'];
strings.sort();
// ['a', 'b', 'c']
In above the sort() method will sort the strings alphabetically in ascending order by default.
You can similarly sort the numbers too.
let numbers = [3, 1, 2];
numbers.sort();
// [1, 2, 3]
This will sort the numbers in ascending order as well.
Note: For descending sorts, you can pass a compare function to sort() - we’ll cover this more in the “Sorting in Descending Order” section below.
Sorting Arrays of Objects
Objects don’t have a default sort order like strings or numbers. You will need to provide a compare function that specifies which property to sort on when sorting arrays of objects in TypeScript. With this compare function you will tell TypeScript how to compare the objects.
Here is an example:
interface Person {
name: string;
age: number;
}
const people: Person[] = [
{name: "Jack", age: 30},
{name: "Mary", age: 25},
{name: "John", age: 40}
];
people.sort((a, b) => {
return a.age - b.age;
});
In this example we are sorting the array of Person objects by the age property in ascending order. This compare function subtracts the age of person A from person B to get a positive or negative number to find out the sorting order. This allows you full control over how TypeScript should sort an array of objects.
Sort by a Single Property
You can sort an array of objects by a single property like name or by age. In TypeScript the Array.sort() method accepts a compare function through which you can compare the name or age property of objects.
For example:
interface Person {
name: string;
age: number;
}
const people: Person[] = [
{name: "John", age: 20},
{name: "Mary", age: 25},
{name: "Mike", age: 30}
];
people.sort((a, b) => {
if(a.name < b.name) return -1;
if(a.name > b.name) return 1;
return 0;
});
console.log(people);
// [
// {name: "John", age: 20},
// {name: "Mary", age: 25},
// {name: "Mike", age: 30}
// ]
In this example the compare function in sort method takes two Person objects a and b. It compares the name property of a and b alphabetically and then it returns -1 if a should come before b, 1 if a should come after b and 0 if a and b are equal.
Similarly, You can sort by any property like age or date of birth. To do that you will only need to change the compare function property.
Sort by Multiple Properties
Also, You can sort any array of objects by multiple properties. For example, if you need to sort the array by name first, then by age:
interface Person {
name: string;
age: number;
}
const people: Person[] = [
{name: "Bob", age: 30},
{name: "Alice", age: 25},
{name: "Bob", age: 20}
];
people.sort((a, b) => {
if (a.name < b.name) return -1;
if (a.name > b.name) return 1;
if (a.age < b.age) return -1;
if (a.age > b.age) return 1;
return 0;
});
console.log(people);
// [
// {name: "Alice", age: 25},
// {name: "Bob", age: 20},
// {name: "Bob", age: 30}
// ]
This example first compares the name property and then sort it alphabetically. When it is done with sorting the names, it will compare the age property and sort them numerically.
So, you can add as many comparison scenarios as you need like above. The array will be sorted by each property in order.
Sorting in Descending Order
If you need to sort an array of objects in descending order, you have to provide a compare function to the sort() method that reverses the default sort order.
Here is an example:
interface User {
name: string;
age: number;
}
const users: User[] = [
{name: "John", age: 30},
{name: "Jane", age: 20},
{name: "Jim", age: 25}
];
users.sort((a, b) => {
if (a.age > b.age) return -1;
if (a.age < b.age) return 1;
return 0;
});
console.log(users);
// [ {name: "John", age: 30}, {name: "Jim", age: 25}, {name: "Jane", age: 20} ]
In this example, the comparison happens between a and b. If a comes after b in ascending order then it returns -1 which indicates that a should come before b in descending order. And similarly, if a comes before b in ascending order, it returns 1 that means that a should come after b in descending order.
If both are equal it will return 0 and that will maintained by their relative order.
You can simplify above compare function by using the ternary operators and can do it in one line:
users.sort((a, b) => a.age > b.age ? -1 : a.age < b.age ? 1 : 0);
It will show the same result as previous function.
Case-Insensitive Sorting
In many cases, we need to sort array of objects that are case-insensitive. eg, “aBc” comes before “XYZ” in ascending order by default.
and to do a case-insensitive sort, we need to convert the strings to lowercase before comparing them in the compare function.
For example:
interface Person {
name: string;
}
let people: Person[] = [
{name: "John"},
{name: "paul"},
{name: "George"},
{name: "Ringo"}
];
people.sort((a, b) => {
let nameA = a.name.toLowerCase();
let nameB = b.name.toLowerCase();
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
return 0;
});
This converts name property of this object to lowercase before the comparison, so the end result is:
[ {name: "George"}, {name: "John"}, {name: "paul"}, {name: "Ringo"} ]
This approach works well for simple case-insensitive sorting of strings.
In case if you need to do more complex sorting, you can use a library like lodash which has built-in case-insensitive sorting functions.
Sorting Nested Objects
When sorting arrays of objects that contain nested objects, we need to access the nested properties in the compare callback function.
For example, if we have an array of objects with a nested address object:
const users = [
{
name: 'John',
address: {
city: 'New York'
}
},
{
name: 'Jane',
address: {
city: 'Los Angeles'
}
}
];
We can sort it by accessing nested city property and then sort it like below:
users.sort((a, b) => {
if(a.address.city < b.address.city) {
return -1;
}
if(a.address.city > b.address.city) {
return 1;
}
return 0;
});
Inside the compare function, we can use a.address.city and b.address.city to access the nested city property and then compare the values. This process works for objects nested at any depth - we just chain the property accessors together to drill down into the nested structure. By accessing the nested properties in the compare callback, we can sort arrays of objects with any level of nesting.
Conclusion
In Typescript coding, it is very important to know sorting arrays and primitives like strings, numbers, and dates. But the most valuable thing is ability to sort arrays of objects by one or more properties. Sorting helps to organize complex data structures in a logical way and makes it easier to work within our code.