@const (also @constant) is a JSDoc documentation tag for a value that should not change. TypeScript 5.9 does not read it: a let tagged @const can be reassigned without an error, and @constant {number} does not even apply its type.
The const keyword is what TypeScript enforces. For an object or array whose contents should also stay fixed, add a const assertion, /** @type {const} */ (value), which makes every property read-only and keeps the literal values as types.
At a glance
| Use | JSDoc in a .js file | TypeScript in a .ts file |
|---|---|---|
| A variable that never changes | const maxItems = 10; | const maxItems = 10; |
| An object whose values never change | const limits = /** @type {const} */ ({ items: 10 }); | const limits = { items: 10 } as const; |
Examples
/** @const */
export let maxItems = 10;
/** @constant {number} */
export let maxWeight = 25;
// TypeScript accepts both: neither tag is read.
maxItems = 50;
maxWeight = 30;jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} export const maxItems = 10;
maxItems = 50;error TS2588: Cannot assign to 'maxItems' because it is a constant.export const maxItems = 10;
maxItems = 50;error TS2588: Cannot assign to 'maxItems' because it is a constant.jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} How we tested it
The first example tags one let with @const and another with @constant {number}, then assigns to both. If TypeScript honored either tag, the assignments would be errors. tsc reports nothing. The second example uses the keyword, and the assignment fails with TS2588 ("Cannot assign to 'maxItems' because it is a constant").
The keyword and the const assertion
const stops reassignment of the variable, not changes to the object it points to: const limits = { items: 10 } still allows limits.items = 50. /** @type {const} */ ({ items: 10 }) makes items read-only and types it as the literal 10; TypeScript 4.5 added this JSDoc form of as const.
Neither is a run-time freeze. Object.freeze stops changes at run time too, and TypeScript types its result as Readonly.
Gotchas
- Do not confuse the
@consttag with@type {const}. The first is ignored; the second is aconstassertion that TypeScript does read. @constant {number}looks like it declares a type, but TypeScript does not take the type from it. Use@type {number}for that.
Questions
Is there a JSDoc equivalent of as const?
Yes: a cast to const, written /** @type {const} */ (expression), with the parentheses. It works since TypeScript 4.5.
Sources
- @constant · JSDoc
- TypeScript 4.5: const assertions and default type arguments in JSDoc · TypeScript release notes
- JSDoc Reference: casts · TypeScript handbook
Last reviewed 20 October 2026.