Skip to main content

As Const And Enums

as const — freeze a value into its most specific type

By default TypeScript widens literals ("a" becomes string). as const stops that: it locks the value to its exact literal type and makes it deeply readonly.

let a = 1 as const;        // type: 1  (not number)
const b = "hello" as const; // type: "hello"

const SKILL_LEVELS = ["Beginner", "Intermediate", "Expert"] as const;
// type: readonly ["Beginner", "Intermediate", "Expert"]
// without `as const` it would be: string[]

Why as const is so useful — derive unions from data

Once an array is as const, you can index it by [number] to get a literal union — one source of truth for both the runtime values and the type.

const SKILL_LEVELS = ["Beginner", "Intermediate", "Expert"] as const;

type Person = {
name: string;
skillLevel: (typeof SKILL_LEVELS)[number]; // "Beginner" | "Intermediate" | "Expert"
};

// the same array still works at runtime:
SKILL_LEVELS.forEach((level) => console.log(level));

Change the array and the type updates itself — no duplicated union to maintain.

enum vs as const — a real distinction

An enum is a TypeScript feature that also emits runtime code (an object) — it's not erased like the rest of the type system.

enum Direction { Up, Down } // compiles to a real JS object at runtime

A const array + as const gives you the same "fixed set of values," stays plain data, and adds zero runtime cost. Many teams prefer the as const union over enum for exactly that reason.

as const says "this literal is final — narrow it, don't widen it." It's the idiomatic, runtime-free way to build a fixed set of options and derive a union type from it.