Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Use LoDash orderBy with dynamic values for ascending or descending sort

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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);
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading