0

I have an array of objects like this. I am trying to sort the array if the holidays have the same holiday_on, and Sort by holiday_for By Descending Order.

const holidays: IHoliday[] = [
    {
        id: 1,
        holiday_for: 1,
        holiday_on: "2021-10-26"
    },
    {
        id: 2,
        holiday_for: 3,
        holiday_on: "2021-10-26"
    },
    {
        id: 3,
        holiday_for: 1,
        holiday_on: "2021-11-26"
    },
    {
        id: 4,
        holiday_for: 3,
        holiday_on: "2021-11-26"
    },
    {
        id: 5,
        holiday_for: 4,
        holiday_on: "2021-11-26"
    }
]

With the implementation below getting this type error Argument of type '(a: IHoliday, b: IHoliday) => number | undefined' is not assignable to parameter of type '(a: IHoliday, b: IHoliday) => number'.Type 'number | undefined' is not assignable to type 'number'

If I make the holidays array any type then typescript giving another warning - Not all code paths return a value.

Implementation

const sorted = holidays.sort((a: IHoliday, b: IHoliday) => {
    if (a.holiday_on === b.holiday_on) {
        return b.holiday_for - a.holiday_for;
    }
});
RAHUL KUNDU
  • 745
  • 2
  • 12
  • 33
  • 1
    Does this answer your question? [Sort array of objects by string property value](https://stackoverflow.com/questions/1129216/sort-array-of-objects-by-string-property-value) – msanford Sep 17 '21 at 03:04
  • I would suggest to use a library underscore or lodash both the libraries have lot of inbuilt utilities – lakshmi narayana Sep 17 '21 at 04:55

2 Answers2

1

I added another return so that if the holiday_on is not the same, it will sort the date but you cannot directly make an operation with the type Date in Typescript. Using getTime() method converts a Date into a number (Date.prototype.getTime()) so you can make the operation without error.

const sorted = this.holidays.sort((a: IHoliday, b: IHoliday) => {
  if (a.holiday_on === b.holiday_on) {
    return b.holiday_for - a.holiday_for;
  }
  return (
    new Date(b.holiday_on).getTime() - new Date(a.holiday_on).getTime()
  );
});
console.log(sorted);

I added a stackblitz for you to play on.

dom.macs
  • 776
  • 7
  • 15
0

Your sort function needs to always return a number. 0 if equal, >=1 if greater, and <=-1 if smaller.

const sorted = holidays.sort((a: IHoliday, b: IHoliday) => {
    if (a.holiday_on === b.holiday_on) {
        return b.holiday_for - a.holiday_for;
    }
    return new Date(b.holiday_on) - new Date(a.holiday_on)
});

This function will attempt to sort by holiday_on first, and only if it's equal, then it sorts by holiday_for.

aelesia
  • 184
  • 7
  • In the second return where you have added `new Date` getting this error - `The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.` – RAHUL KUNDU Sep 17 '21 at 02:59
  • Code should work if you ignore the error, but to be more specific you can use `return new Date(b.holiday_on).getTime() - new Date(a.holiday_on).getTime()` – aelesia Sep 19 '21 at 15:52