How to Sort by Enum in TypeScript?

Recently, I was working on a TypeScript project where I needed to sort a list of items based on their status. The status was represented as an enum, and I wanted the items to appear in a specific order based on these enum values.

The challenge was that TypeScript enums don’t inherently provide sorting capabilities. I had to figure out the best approach to sort elements based on enum values.

In this article, I’ll share multiple methods to sort arrays by enum in TypeScript, including sorting by enum type, value, and key. So let’s dive in!

Understanding TypeScript Enums

Before we jump into sorting, let’s quickly understand what enums are in TypeScript:

enum Priority {
  Low = 0,
  Medium = 1,
  High = 2,
  Critical = 3
}

Enums allow us to define a set of named constants, making our code more readable and maintainable. In the example above, each priority level has an associated numeric value.

Method 1: Sorting by Enum Value

The most common scenario is sorting an array of objects that contain enum values in TypeScript. Let’s look at a practical example using a task management system:

enum TaskStatus {
  Completed = 0,
  InProgress = 1,
  NotStarted = 2,
  Blocked = 3
}

interface Task {
  id: number;
  title: string;
  status: TaskStatus;
}

// Sample data
const tasks: Task[] = [
  { id: 1, title: "Prepare quarterly report", status: TaskStatus.NotStarted },
  { id: 2, title: "Update client documentation", status: TaskStatus.Completed },
  { id: 3, title: "Fix payment gateway bug", status: TaskStatus.Blocked },
  { id: 4, title: "Implement new dashboard", status: TaskStatus.InProgress }
];

// Sort tasks by status
const sortedTasks = [...tasks].sort((a, b) => a.status - b.status);

console.log(sortedTasks);

In this example, we’re sorting tasks based on their status values. Since enum values are numbers under the hood, we can simply subtract them to determine the sort order.

You can see the exact output in the screenshot below:

typescript sort by enum

This works perfectly when your enum values are sequential numbers, which is the default behavior in TypeScript.

Check out Convert String to Enum in TypeScript

Method 2: Sorting by Custom Enum Order

Sometimes, you might want a custom sort order that doesn’t match the enum’s numeric values. For example, you might want to display blocked tasks first, followed by in-progress, not started, and completed tasks:

enum TaskStatus {
  Completed = 0,
  InProgress = 1,
  NotStarted = 2,
  Blocked = 3
}

// Define custom sort order
const statusSortOrder = {
  [TaskStatus.Blocked]: 0,    // Show blocked tasks first
  [TaskStatus.InProgress]: 1, // Then in-progress tasks
  [TaskStatus.NotStarted]: 2, // Then not started tasks
  [TaskStatus.Completed]: 3   // Finally completed tasks
};

// Sort tasks by custom status order
const customSortedTasks = [...tasks].sort((a, b) => 
  statusSortOrder[a.status] - statusSortOrder[b.status]
);

console.log(customSortedTasks);

This approach gives you complete flexibility in defining your sort order, regardless of the actual enum values.

Read How to Iterate Over Enums in TypeScript?

Method 3: Sorting by Enum Key (String)

If you’re using string enums or need to sort by the enum key names rather than their values, you can do that too:

enum Department {
  Sales = "SALES",
  Marketing = "MARKETING",
  Engineering = "ENGINEERING",
  Support = "SUPPORT"
}

interface Employee {
  id: number;
  name: string;
  department: Department;
}

const employees: Employee[] = [
  { id: 101, name: "John Smith", department: Department.Engineering },
  { id: 102, name: "Sarah Johnson", department: Department.Sales },
  { id: 103, name: "Michael Brown", department: Department.Marketing },
  { id: 104, name: "Emily Davis", department: Department.Support }
];

// Sort employees by department name alphabetically
const sortedEmployees = [...employees].sort((a, b) => 
  a.department.localeCompare(b.department)
);

console.log(sortedEmployees);

Since string enums retain their string values at runtime, we can use localeCompare() to sort them alphabetically.

Here is the exact output in the screenshot below:

typescript sort by enum type

Check out Check If a String Is in an Enum in TypeScript

Method 4: Getting Enum Key by Value for Sorting

Sometimes, you might need to sort based on the enum key (the name) but only have access to the enum value. Here’s how to handle that:

enum ProductCategory {
  Electronics = 0,
  Clothing = 1,
  Books = 2,
  HomeGoods = 3
}

interface Product {
  id: number;
  name: string;
  category: ProductCategory;
}

const products: Product[] = [
  { id: 1, name: "Laptop", category: ProductCategory.Electronics },
  { id: 2, name: "T-shirt", category: ProductCategory.Clothing },
  { id: 3, name: "JavaScript Guide", category: ProductCategory.Books },
  { id: 4, name: "Coffee Maker", category: ProductCategory.HomeGoods }
];

// Helper function to get enum key from value
function getEnumKeyByValue(enumType: any, value: number | string): string {
  return Object.keys(enumType).find(key => enumType[key] === value) || '';
}

// Sort products by category name
const sortedProducts = [...products].sort((a, b) => {
  const categoryNameA = getEnumKeyByValue(ProductCategory, a.category);
  const categoryNameB = getEnumKeyByValue(ProductCategory, b.category);
  return categoryNameA.localeCompare(categoryNameB);
});

console.log(sortedProducts);

This method is particularly useful when you need to display the readable enum keys in a sorted order.

Read Convert TypeScript Enums to Arrays

Method 5: Sorting with Enum Mapping for Complex Objects

For more complex scenarios, you might want to use a mapping approach that translates enum values to sortable weights:

enum UserRole {
  Admin = "ADMIN",
  Manager = "MANAGER",
  Editor = "EDITOR",
  Viewer = "VIEWER"
}

// Define the sort weight for each role (lower number = higher priority)
const roleSortWeight = {
  [UserRole.Admin]: 0,
  [UserRole.Manager]: 1,
  [UserRole.Editor]: 2,
  [UserRole.Viewer]: 3
};

interface User {
  id: number;
  name: string;
  role: UserRole;
  department: string;
}

const users: User[] = [
  { id: 1, name: "Alice", role: UserRole.Editor, department: "Content" },
  { id: 2, name: "Bob", role: UserRole.Admin, department: "IT" },
  { id: 3, name: "Carol", role: UserRole.Viewer, department: "Marketing" },
  { id: 4, name: "Dave", role: UserRole.Manager, department: "Operations" }
];

// Sort users by role importance, then by name alphabetically
const sortedUsers = [...users].sort((a, b) => {
  // First sort by role weight
  const roleComparison = roleSortWeight[a.role] - roleSortWeight[b.role];
  
  // If roles are the same, sort by name
  if (roleComparison === 0) {
    return a.name.localeCompare(b.name);
  }
  
  return roleComparison;
});

console.log(sortedUsers);

This method is particularly powerful as it allows for multi-level sorting, first by enum-based criteria and then by other properties.

You can see the exact output in the screenshot below:

typescript sort by enum value

Check out How to Use TypeScript Enum Reverse Mapping

TypeScript Sort by Enum Type

When working with discriminated unions and type narrowing, you might want to sort based on the type itself:

enum ShapeType {
  Circle = "CIRCLE",
  Square = "SQUARE",
  Triangle = "TRIANGLE"
}

type Circle = {
  type: ShapeType.Circle;
  radius: number;
};

type Square = {
  type: ShapeType.Square;
  sideLength: number;
};

type Triangle = {
  type: ShapeType.Triangle;
  base: number;
  height: number;
};

type Shape = Circle | Square | Triangle;

// Sample shapes
const shapes: Shape[] = [
  { type: ShapeType.Square, sideLength: 5 },
  { type: ShapeType.Circle, radius: 3 },
  { type: ShapeType.Triangle, base: 4, height: 6 },
  { type: ShapeType.Circle, radius: 2 },
  { type: ShapeType.Square, sideLength: 7 }
];

// Define type priority
const shapePriority = {
  [ShapeType.Circle]: 0,
  [ShapeType.Square]: 1,
  [ShapeType.Triangle]: 2
};

// Sort by shape type
const sortedShapes = [...shapes].sort((a, b) => 
  shapePriority[a.type] - shapePriority[b.type]
);

console.log(sortedShapes);

In this example, I’m sorting shapes based on their type, with circles appearing first, followed by squares and then triangles. This approach is incredibly useful when working with TypeScript’s discriminated union types.

Check out Check If a Value Is in an Enum in TypeScript

Sorting by Enum Key in TypeScript

Sometimes you might need to sort by the actual enum key names instead of their values. Object.keys() can help us achieve this:

enum PaymentMethod {
  CreditCard = "CC",
  BankTransfer = "BT",
  PayPal = "PP",
  ApplePay = "AP"
}

// Get enum keys as an array
const paymentMethodKeys = Object.keys(PaymentMethod)
  .filter(key => isNaN(Number(key))); // Filter out numeric keys

// Sort the keys alphabetically
const sortedKeys = [...paymentMethodKeys].sort();

console.log(sortedKeys); // ["ApplePay", "BankTransfer", "CreditCard", "PayPal"]

// Now we can map back to enum values if needed
const sortedEnumValues = sortedKeys.map(key => PaymentMethod[key as keyof typeof PaymentMethod]);

console.log(sortedEnumValues); // ["AP", "BT", "CC", "PP"]

This technique is especially useful when you need to present enum options in a sorted dropdown menu or list.

Here is the output in the screenshot below:

typescript sort by enum key

Read TypeScript Switch with Enums

Using Library Support for Enum Sorting

If you’re working on a larger project, you might want to consider using ESLint rules to enforce consistent enum sorting. The sort-enums rule from ESLint Plugin Perfectionist can automatically sort your enum declarations alphabetically or in custom order:

// Before sorting
enum Direction {
  Down,
  Left,
  Right,
  Up
}

// After sorting (alphabetically)
enum Direction {
  Down,
  Left,
  Right,
  Up
}

This ensures consistent enum definitions across your codebase and improves maintainability.

Check out Convert Enums to Strings in TypeScript

Advanced: Sorting with Enum Reflection

TypeScript enums have some interesting runtime characteristics that we can leverage for more advanced sorting scenarios:

enum ServiceTier {
  Free = 0,
  Basic = 1,
  Premium = 2,
  Enterprise = 3
}

// Create a reverse mapping for debugging or display purposes
const tierNames: Record<number, string> = {};
for (const key in ServiceTier) {
  const value = ServiceTier[key];
  if (typeof value === 'number') {
    tierNames[value] = key;
  }
}

interface Customer {
  id: number;
  name: string;
  tier: ServiceTier;
}

const customers: Customer[] = [
  { id: 1, name: "Acme Corp", tier: ServiceTier.Enterprise },
  { id: 2, name: "Startup Inc", tier: ServiceTier.Basic },
  { id: 3, name: "Local Business", tier: ServiceTier.Free },
  { id: 4, name: "Tech Giant", tier: ServiceTier.Premium }
];

// Sort customers by service tier (descending order)
const sortedCustomers = [...customers].sort((a, b) => b.tier - a.tier);

// Display with tier names
console.log(sortedCustomers.map(customer => ({
  ...customer,
  tierName: tierNames[customer.tier]
})));

This approach gives you both the performance benefits of sorting by numeric enum values and the readability of displaying the enum key names.

Check out How to Get Enum by Name in TypeScript

Performance Considerations

When sorting large arrays using TypeScript enums, performance can become a concern. Here are some tips:

  1. Pre-compute sort values: If your sort logic is complex, consider pre-computing sort values or weights.
  2. Memoize enum lookups: If you’re converting between enum values and keys repeatedly, memoize these operations.
  3. Use numeric enums for sorting: Numeric comparisons are faster than string comparisons, so prefer numeric enums when sorting is a primary concern.
// Performance optimization example
enum Priority {
  Low = 0,
  Medium = 1,
  High = 2,
  Critical = 3
}

interface Task {
  id: string;
  title: string;
  priority: Priority;
}

const tasks: Task[] = [/* many tasks here */];

// Pre-compute sort values (with added stability)
const enhancedTasks = tasks.map((task, index) => ({
  ...task,
  sortValue: (task.priority * 10000) + index // Preserve original order for equal priorities
}));

// Sort using pre-computed values
enhancedTasks.sort((a, b) => b.sortValue - a.sortValue);

// Extract original tasks in sorted order
const sortedTasks = enhancedTasks.map(({ sortValue, ...task }) => task);

This technique is particularly useful when sorting the same dataset multiple times or when working with very large arrays.

Summary

In this tutorial, I explained how to sort by enum in TypeScript. Throughout this article, we’ve explored various methods to sort by enum type, value, and key.

Remember that the best approach depends on your specific use case:

  • For simple numeric enums, direct comparison works well
  • For custom sort orders, use a mapping object
  • For string enums, string comparison methods like localeCompare() are appropriate
  • For complex scenarios, consider multi-level sorting or pre-computing sort values

You may also like:

Power Apps functions free pdf

30 Power Apps Functions

This free guide walks you through the 30 most-used Power Apps functions with real business examples, exact syntax, and results you can see.

Download User registration canvas app

DOWNLOAD USER REGISTRATION POWER APPS CANVAS APP

Download a fully functional Power Apps Canvas App (with Power Automate): User Registration App