Union of Literals as an Alternative

The Modern Alternative

A union of string literals gives the same safety with no runtime code. Combine it with an as const array when you also need the list of values at runtime.

Example

(typeof STATUSES)[number] means "the type of any element of this array", so the type is generated from the array and the two can never get out of sync.

const STATUSES = ["PLACED", "SHIPPED", "DELIVERED"] as const;
type OrderStatus = (typeof STATUSES)[number]; // "PLACED" | "SHIPPED" | "DELIVERED"

function isOrderStatus(value: string): value is OrderStatus {
  return (STATUSES as readonly string[]).includes(value);
}

function canCancel(status: OrderStatus): boolean {
  return status === "PLACED";
}

console.log(canCancel("PLACED")); // plain strings work
console.log(STATUSES.join(" -> "));
const fromApi = "SHIPPED";
if (isOrderStatus(fromApi)) console.log("valid status:", fromApi);

Output

true
PLACED -> SHIPPED -> DELIVERED
valid status: SHIPPED

Which One to Choose

enumconst enumliteral union
Runtime objectyesnono (add an as const array if needed)
Accepts plain stringsnonoyes
Works with isolatedModulesyesriskyyes
Reverse mappingnumeric onlynono
Common inAngular, NestJS, older codelibrariesReact, Next.js, modern code

Tip: Both styles are fine in interviews. Know that enums produce runtime code and literal unions do not.