2 min read

TypeScript const Assertions (as const)

TypeScript 3.4 introduced a new construct for literal values called const assertions. Its syntax is a type assertion with const in place of the type name (e.g., 123 as const).

When you construct a new literal expression with a const assertion, you signal to the compiler:

  1. No Widening: Literal types should not be widened (e.g., no going from "hello" to string).
  2. Readonly: Object properties get readonly modifiers.
  3. Tuples: Arrays become readonly tuples.

1. Preventing Type Widening

By default, if you assign a string literal to a variable (using let), TypeScript infers it as string.

// Type: string
let x = "hello";

// Type: "hello"
let y = "hello" as const;

This is useful when you want to ensure a variable holds a specific literal value and nothing else.

2. Objects become Readonly

When you use as const on an object, all its properties automatically become readonly, and their types are narrowed to their literal values.

const config = {
  endpoint: "https://api.example.com",
  retries: 3
};
// Type: { endpoint: string; retries: number; }
// Properties are mutable.

const strictConfig = {
  endpoint: "https://api.example.com",
  retries: 3
} as const;
// Type: { readonly endpoint: "https://api.example.com"; readonly retries: 3; }
// Properties are immutable.

// strictConfig.retries = 5; // Error: Cannot assign to 'retries' because it is a read-only property.

3. Arrays become Readonly Tuples

By default, an array of mixed types is inferred as (TypeA | TypeB)[]. With as const, it becomes a fixed-length, readonly tuple.

const args = [8, 5];
// Type: number[]

const strictArgs = [8, 5] as const;
// Type: readonly [8, 5]

This is extremely useful for React hooks or functions that return tuples.

function useToggle() {
  let state = true;
  const toggle = () => state = !state;

  // Without 'as const', TS infers (boolean | () => boolean)[]
  // With 'as const', TS infers readonly [boolean, () => boolean]
  return [state, toggle] as const;
}

const [value, set] = useToggle();
// value is boolean
// set is () => boolean

4. Complex Nested Structures

as const applies recursively.

const menu = {
  home: { label: "Home", link: "/" },
  about: { label: "About", link: "/about" }
} as const;

programming/javascript/typescript/typescript