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?
CodePudding user response:
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.
CodePudding user response:
You say !'string'
which is always false. Because the exclamation mark is casting the variable (value) to boolean and negating it.
So You actually say:
false !== 'string'
Which is always true
. that's why it says "This condition will always return 'true'"
CodePudding user response:
The ! before a and b string variables are the problem. if (!a.role !== 'External' && b.role !== 'External') return 1
evaluates to "if (true !== 'External'.... Remove those ! for if (a.role !== 'External' && b.role !== 'External') return 1
.
CodePudding user response:
You could take a more concise approach by using deltas of the conditions.
const
array = [{ role: 'other', selected: false }, { role: 'External', selected: false }, { role: 'External', selected: false }, { role: 'other', selected: true }, { role: 'other', selected: false }];
array.sort((a, b) =>
b.selected - a.selected ||
(a.role === 'External' && !a.selected) - (b.role === 'External' && !b.selected)
);
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }