The LoDash orderBy function is pretty straightforward – you pass it the collection you want to sort, the properties you want to sort by, and then optionally whether the sort on those properties should be ascending or descending. A typical usage might look like this:
let sortedCollection = _.orderBy(unsortedCollection, ['columnA', 'columnB'], ['asc', 'desc']);
I need to be able to dynamically set both the properties to sort by as well as whether the sort should be ascending or descending for each of those properties. I’ve had no issues dynamically setting the properties to sort by, but I cannot figure out how to dynamically set the ascending/descending option. I have a SortOrderItem object with a name and order property. If order is true then that property should be sorted ascending, otherwise descending.
namespace app.models {
export class SortOrderItem {
name: string;
order: boolean;
}
}
I have an array of these (stored in an array named sortOrder) that is set in the UI and when I want to sort my collection I loop through the array to build the properties and (hopefully) the sort order:
private getSortedRecords(unsortedCollection: any[]): any[] {
let sortColumns: string[] = [];
let sortOrders: string[] = [];
_.forEach(this.sortOrder,
(item: models.SortOrderItem) => {
sortColumns.push(item.name);
sortOrders.push(item.order ? 'asc' : 'desc');
});
return _.orderBy(unsortedCollection, sortColumns, sortOrders);
}
However, this doesn’t work because it doesn’t like the array of strings for the 3rd parameter. I get:
TS2769: (TS) No overload matches this call.
The last overload gave the following error.
Argument of type 'string[]' is not assignable to a parameter of type 'Many <boolean | "asc" | "desc">'.
Type 'string[]' is not assignable to type 'readonly (boolean | "asc" | "desc")[]'.
Type 'string' is not assignable to type 'boolean | "asc" | "desc"'.
So then I tried using readonly(boolean|'asc'|'desc')[] as the type for my sortOrders variable:
let sortOrders: readonly(boolean|'asc'|'desc')[] = [];
This doesn’t work because then I get this error:
TS2339: (TS) Property 'push' does not exist on type 'readonly (boolean|"asc"|"desc")[]'.
How can I set this up so I can define the last parameter dynamically?
>Solution :
Define a SortOrder type:
type SortOrder = 'asc' | 'desc';
And use it as the type of sortOrders:
function getSortedRecords(unsortedCollection: any[]): any[] {
const sortColumns: string[] = [];
const sortOrders: SortOrder[] = [];
_.forEach(this.sortOrder,
(item: SortOrderItem) => {
sortColumns.push(item.name);
sortOrders.push(item.order ? 'asc' : 'desc');
});
return _.orderBy(unsortedCollection, sortColumns, sortOrders);
}