Skip to main content
Practice Problems

Const assertions (as const) in TypeScript

What is as const?

as const is a const assertion that tells TypeScript to infer the narrowest possible type for a value — making it deeply readonly with literal types instead of widened types.


Without vs With as const

typescript
// Without as const — widened types const config = { url: "https://api.example.com", port: 3000, methods: ["GET", "POST"] }; // type: { url: string; port: number; methods: string[] } // With as const — narrowed to literals and readonly const config = { url: "https://api.example.com", port: 3000, methods: ["GET", "POST"] } as const; // type: { // readonly url: "https://api.example.com"; // readonly port: 3000; // readonly methods: readonly ["GET", "POST"]; // }

What as const Does

AspectWithout as constWith as const
String valuesstringLiteral ("exact value")
Number valuesnumberLiteral (42)
Object propertiesMutablereadonly
ArraysMutable arrayreadonly tuple
Nested objectsMutableDeeply readonly

Common Use Cases

Creating Union Types from Values

typescript
const ROLES = ["admin", "editor", "viewer"] as const; type Role = typeof ROLES[number]; // "admin" | "editor" | "viewer" const STATUS = { PENDING: "pending", ACTIVE: "active", INACTIVE: "inactive", } as const; type Status = typeof STATUS[keyof typeof STATUS]; // "pending" | "active" | "inactive"

Enum Alternative

typescript
// Instead of enum: enum Direction { Up = "UP", Down = "DOWN", Left = "LEFT", Right = "RIGHT" } // Use as const: const Direction = { Up: "UP", Down: "DOWN", Left: "LEFT", Right: "RIGHT", } as const; type Direction = typeof Direction[keyof typeof Direction]; // "UP" | "DOWN" | "LEFT" | "RIGHT"

Function with Literal Return

typescript
function getConfig() { return { theme: "dark", lang: "en", features: ["search", "notifications"], } as const; } const config = getConfig(); config.theme; // "dark" (literal, not string) config.features[0]; // "search" (literal)

Discriminated Unions

typescript
const createAction = <T extends string, P>(type: T, payload: P) => ({ type, payload } as const); const increment = createAction("INCREMENT", { amount: 1 }); // { readonly type: "INCREMENT"; readonly payload: { readonly amount: 1 } }

Tuple Arguments

typescript
// Without as const const args = [1, "hello"]; // (string | number)[] // With as const const args = [1, "hello"] as const; // readonly [1, "hello"] function foo(num: number, str: string) {} foo(...args); // ✅ Works because TypeScript knows exact types

as const vs Object.freeze

Featureas constObject.freeze
WhenCompile timeRuntime
DepthDeep readonlyShallow
Literal typesYesNo
Runtime effectNonePrevents modification
typescript
// For maximum immutability: combine both const config = Object.freeze({ api: "https://api.example.com", version: 1, } as const);

Important:

as const is essential for creating type-safe constants, enum alternatives, and literal union types from values. It's a compile-time-only feature with zero runtime cost. Use it whenever you need TypeScript to infer the most specific type possible.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?
Practice Problems