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:
- No Widening: Literal types should not be widened (e.g., no going from
"hello"tostring). - Readonly: Object properties get
readonlymodifiers. - Tuples: Arrays become
readonlytuples.
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;