'Handle null with localecompare typescript
I have the following sort:
let sortedCon = this.con.sort((a, b) => a.lastname.localeCompare(b.lastname));
I am trying to get it to handle nulls and maintain the one line simplicity.
I have tried this but not working:
let sortedCon = this.con.sort((a, b) => a ? a.lastname.localeCompare(b ? b.lastname : '') : 0);
I know I am close but cant figure it out. Any help would be appreciated.
Solution 1:[1]
Without a minimum reproducible example including the type definitions for this.con
as well as the particular sort order you'd like to see (if an element of this.con
is not defined, should it sort in the same place as if it were defined with an empty lastname
? or somewhere else?), it's hard to be sure, but assuming it's something like:
declare const con: Array<{
lastname?: string | null
} | null | undefined>;
then you can use the optional chaining and nullish coalescing operators introduced in TypeScript 3.7 to get the following one-liner:
con.sort((a, b) => (a?.lastname ?? "").localeCompare(b?.lastname ?? ""));
The optional chaining in a?.lastname
is similar to (a != null ? a.lastname : undefined)
, and the nullish coalescing expr ?? ""
is similar to (expr != null ? expr : "")
. So that together produces something similar to
con.sort((a, b) => ((a || {}).lastname || "").localeCompare((b || {}).lastname || ""));
which is uglier but should work in TS3.6 and below. Both of these make the elements null
, {lastname: undefined}
, {lastname: null}
, and {lastname: ""}
all interchangeable in terms of the sort order. If you want to see those sorted in some particular order with respect to each other or with respect to elements with non-empty lastname
properties, then you should specify that in the question.
Let's see how it acts:
const con: Array<{ lastname?: string | null } | null | undefined> = [
{ lastname: "" },
{ lastname: "B" },
{ lastname: null },
null,
{ lastname: "A" },
{},
{ lastname: "C" }
]
console.log(JSON.stringify(con));
// [{"lastname":""},{"lastname":"B"},{"lastname":null},null,{"lastname":"A"},{},{"lastname":"C"}]
Sorting with the TS3.7 code:
const newCon = con.slice();
newCon.sort((a, b) => (a?.lastname ?? "").localeCompare(b?.lastname ?? ""));
console.log(JSON.stringify(newCon));
// [{"lastname":""},{"lastname":null},null,{},{"lastname":"A"},{"lastname":"B"},{"lastname":"C"}]
and with the TS3.6- code:
const newCon2 = con.slice();
newCon2.sort((a, b) => ((a || {}).lastname || "").localeCompare((b || {}).lastname || ""));
console.log(JSON.stringify(newCon2));
// [{"lastname":""},{"lastname":null},null,{},{"lastname":"A"},{"lastname":"B"},{"lastname":"C"}]
both yields the same ordering, where the "empty" elements are moved to the front and in the original order from the array (you can't count on Array.prototype.sort
being stable but it usually is), and the rest of the elements are sorted in order of the lastname
property.
Anyway, hope that helps; good luck!
Solution 2:[2]
Have you tried something like this?
let sortedCon = this.con.sort((a, b) => a && a.lastname && a.lastname.localeCompare(b && b.lastname : '') : 0);
Solution 3:[3]
It's easy, you need to evaluate the lastname field, if the lastname is null change it to an empty string ---> ""
this.con.sort((a:any, b:any) => (a.lastName || "").localeCompare(b.lastName || "")
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 |