Typescript Sorting based on Enum constants

If you look at the compiled javascript of your enum:

var MyEnum;
(function (MyEnum) {
    MyEnum[MyEnum["VALUE_1"] = 0] = "VALUE_1";
    MyEnum[MyEnum["VALUE_3"] = 1] = "VALUE_3";
    MyEnum[MyEnum["VALUE_2"] = 2] = "VALUE_2";
})(MyEnum || (MyEnum = {}));

You'll see that each gets an ordinal number based on the position, so the first is 0 and the last is 2.

If you refer to an enum you'll just get a number back:

console.log(MyEnum.VALUE_3); // 1

If you want to sort your list:

let list = [MyEnum.VALUE_3, MyEnum.VALUE_1, MyEnum.VALUE_2];
console.log(list); // [1, 0, 2]
list.sort((a, b) => a - b);
console.log(list); // [0, 1, 2]

If you want the list of the string names of the enum sorted by the ordinal then you can do:

let names = list.map(ordinal => MyEnum[ordinal]);
console.log(names); // ["VALUE_1", "VALUE_3", "VALUE_2"]

(code in playground)


Edit

You can sort in the same way, regardless of how you set the enum values, you just need to change the compare function.
For example, this will sort the list based on the lexicographical order of the enum string values:

enum MyEnum {
    VALUE_1 = "value 1" as any,
    VALUE_3 = "value 3" as any,
    VALUE_2 = "value 2" as any
}

let list = [MyEnum.VALUE_3, MyEnum.VALUE_1, MyEnum.VALUE_2];
console.log(list); // ["value 3", "value 1", "value 2"]
list.sort((a, b) => {
    if (a < b) return -1;
    if (a > b) return 1;
    return 0;
});
console.log(list); // ["value 1", "value 2", "value 3"]

let names = list.map(ordinal => MyEnum[ordinal]);
console.log(names); // ["VALUE_1", "VALUE_2", "VALUE_3"]

(code in playground)


Edit #2

Sorting by the original order of the enum is tricky, you can try:

enum MyEnum {
    VALUE_1 = "value 1" as any,
    VALUE_3 = "value 3" as any,
    VALUE_2 = "value 2" as any
}

let list = [MyEnum.VALUE_3, MyEnum.VALUE_1, MyEnum.VALUE_2];
console.log(list); // ["value 3", "value 1", "value 2"]

let sorted = [] as MyEnum[];
let index = 0;
for (let key in MyEnum) {
    if (index % 2 === 0) {
        sorted.push(key as any);
    }

    index++;
}

console.log(sorted); // ["VALUE_1", "VALUE_3", "VALUE_2"]

let names = sorted.map(ordinal => MyEnum[ordinal]);
console.log(names); // ["value 1", "value 3", "value 2"]

(code in playground)

This seems to work, but you shouldn't count on the order which is received in the for/in loop, unless you don't care about cross-browser behavior (or to be specific explorer support), you can read about it in MDN.


Here is another solution. This would prevent flaws even if other contributors to your code change the order of the enum.

enum Action {
    EAT = 'EAT',
    PLAY = 'PLAY',
    SING = 'SING',
    SLEEP = 'SLEEP',
}

const actionOrder = {
    [Action.SING] : 1,
    [Action.PLAY] : 2,
    [Action.EAT] : 3,
    [Action.SLEEP] : 4,  
} as const;

const users = [{
    "name": "Mike",
    "action": Action.EAT
}, {
    "name": "John",
    "action": Action.SLEEP
}, {
    "name": "Harry",
    "action": Action.PLAY
}
];

users.sort((a,b) => {
    return actionOrder[a.action] - actionOrder[b.action];
});

console.log(users);

Had the same problem just now. This is my solution:

enum Weekday {
  MONDAY = 'MONDAY',
  TUESDAY = 'TUESDAY',
  WEDNESDAY = 'WEDNESDAY',
  THURSDAY = 'THURSDAY',
  FRIDAY = 'FRIDAY',
  SATURDAY = 'SATURDAY',
  SUNDAY = 'SUNDAY'
}

const weekdayOrder = Object.values(Weekday);

const weekdaysToBeSorted = [Weekday.TUESDAY, Weekday.MONDAY, Weekday.FRIDAY];

const sortedWeekdays = weekdaysToBeSorted
  .sort((a, b) => weekdayOrder.indexOf(a) - weekdayOrder.indexOf(b))