What does `as const` do, and when would you prefer a literal union over a TypeScript enum?
Understanding literal narrowing, readonly inference, and the runtime cost of enums.
By default TypeScript widens literals: `let s = 'circle'` is inferred as string. `as const` freezes a value to its narrowest, deeply-readonly literal form — a string becomes its literal type, an array becomes a readonly tuple, and object properties become readonly with literal values. That is how you derive a union type from a runtime array: `typeof COLORS[number]`. Prefer a literal union (`type Color = 'red' | 'blue'`) over an enum in most cases: unions are erased at compile time (zero runtime code), they interoperate directly with plain string data from APIs, and `as const` objects give you the same grouping without emitting a bidirectional mapping object. Reach for a real enum only when you specifically want a named runtime namespace or numeric auto-increment. Note `const enum` avoids the runtime object but has its own build/isolatedModules caveats. The single-source pattern — define the array once with `as const`, derive both the values and the type from it — eliminates the drift between a type and its runtime list.
Deriving a union from a config array, typing action strings, and avoiding enum runtime overhead.