Search code examples
javascripttypescriptprettier

sorting a javascript array of objects by 2 values


I have an array of objects, and I want the selected object to always be first. Then, if the object has a role === External but it's not selected, I want that to always by last. If it doesn't match either, it's just in between the two.

const exampleObj = [
  { role: 'other', selected: false },
  { role: 'External', selected: false },
  { role: 'External', selected: false },
  { role: 'other', selected: true },
  { role: 'other', selected: false },
]

This works:

  exampleObj.sort((a, b) => {
        if (!a.selected && b.selected) return 1
        if (a.selected && !b.selected) return -1
        if (!a.role !== 'External' && b.role !== 'External') return 1
        if (a.role !== 'External' && !b.role !== 'External') return -1
        return 0

But I'm getting the prettier error

TS2367: This condition will always return 'true' since the types 'boolean' and 'string' have no overlap.
    108 |             if (!a.selected && b.selected) return 1
    109 |             if (a.selected && !b.selected) return -1
  > 110 |             if (!a.role !== 'External' && b.role !== 'External') return 1
        |                 ^^^^^^^^^^^^^^^^^^^^^^
    111 |             if (a.role !== 'External' && !b.role !== 'External') return -1
    112 |             return 0
    113 |           })

TS2367: This condition will always return 'true' since the types 'boolean' and 'string' have no overlap.
    109 |             if (a.selected && !b.selected) return -1
    110 |             if (!a.role !== 'External' && b.role !== 'External') return 1
  > 111 |             if (a.role !== 'External' && !b.role !== 'External') return -1
        |                                          ^^^^^^^^^^^^^^^^^^^^^^
    112 |             return 0
    113 |           })
    114 |         : []

But if I remove those 2 lines, it's obviously not going to push the External to the end. What am I missing here?


Solution

  • You could use a.role === 'External' && b.role !== 'External' instead

    !a.role !== 'External' is same as false !== 'External' because !a.role will be evaluated first and the result is compared to the string.