TypeScriptUnions and narrowing
as const
Freezes literals in an expression: the narrowest types and read-only fields.
Example
#TypeScript
const LEVELS = ['easy', 'medium', 'hard'] as const
type Level = (typeof LEVELS)[number]
// type Level = "easy" | "medium" | "hard"
function isLevel(value: string): value is Level {
return (LEVELS as readonly string[]).includes(value)
}
console.log(LEVELS.length)
console.log(isLevel('hard'), isLevel('expert'))Result
3 true false
Definition and usage
#The as const assertion makes TypeScript infer the narrowest possible types: strings become literals ("dark" instead of string), arrays become read-only tuples, and object fields become readonly.
This lets you derive a union of allowed values from a single constant: const LEVELS = ["easy", "hard"] as const and type Level = typeof LEVELS[number] gives "easy" | "hard".
It’s a popular alternative to enums. The values exist in JavaScript as a plain array or object, and the types are generated from them automatically.
Syntax
#Syntax
const constant = expression as constMore examples
#TypeScript
const Status = {
Draft: 'draft',
Published: 'published'
} as const
type Status = (typeof Status)[keyof typeof Status]
// type Status = "draft" | "published"
const current: Status = Status.Published
console.log(current)Result
published
Good practices
#- The pattern
const X = [...] as constwithtype T = typeof X[number]gives you both a list of values to loop over and a union type. - An object with
as constis a lighter alternative to an enum, and it doesn’t generate any extra code.
Related entries
#- Literal typesTypes that allow only specific values, e.g. "easy" | "hard".
- enumA named set of constant values, either numbers or strings.
- typeof (in types)Gets the type of a variable or value so you can use it somewhere else.
- readonlyA modifier that blocks changing a field after the object is created.
- satisfiesChecks that a value matches a type without changing the inferred type.
Spotted a mistake or missing an example? Write to us.