PL EN

Separate the logic from the UI layer with the Enum type

At least a few times I've already seen in code an Enum that has a directly assigned string values.

An example below.

enum PaymentStatus {
    Pending = "PENDING",     
    Paid = "PAID",  
    Rejected = "REJECTED",   
}

This approach leads to potential problems for the future:

  • ties the logic to the UI layer,
  • makes translation more difficult,
  • complicates testing,
  • increases the risk of errors in frontend-backend communication.

Let's assume that we use PaymentStatus in the PaymentBadge component:

function PaymentBadge(status: PaymentStatus) {
    return <span className={`badge-${status.toLowerCase()}`}>{status}</span>
}

If we want to change the visible text or class then we have to edit the Enum or add a helper function. The bigger the system, the bigger the pain.

This is just one of the problems we may face during application development.

Treating Enum as a purely logical symbol will indeed make our work easier.

enum PaymentStatus {
    Pending,     
    Paid,  
    Rejected,   
}

Now we can create helper functions that map the required values.

const statusLabel = new Map<PaymentStatus, string>([
  [PaymentStatus.Pending,      'Waiting'],
  [PaymentStatus.Paid,         'Completed'],
  [PaymentStatus.Rejected,     'Failed'],
]);

const statusColorValues = new Map<PaymentStatus, string>([
  [PaymentStatus.Pending,      'red'],
  [PaymentStatus.Paid,         'blue'],
  [PaymentStatus.Rejected,     'green'],
]);

PaymentBadge component after the update.

function PaymentBadge(status: PaymentStatus) {
    return <span class={`badge-${statusColorValues.get(status)}`}>
    {statusLabel.get(status)}</span>
}

With this approach, we decloupled the visual layer from the logic. As a result, the Enum becomes a single source of truth about the state, rather than a method of presentation, translation or serialization.

Go back to articles