Type expression

const assertions

  • Importing and casting
  • Since TypeScript 4.5

A cast to const, /** @type {const} */ (value), is the JavaScript spelling of TypeScript's as const. TypeScript then keeps every literal as its own type ("/cart", not string), makes every property readonly, and turns array literals into read-only tuples. TypeScript 4.5 added the JSDoc form.

It is the usual way to define a fixed set of values once and derive a type from it: (typeof ROUTES)[keyof typeof ROUTES] is the union of the route paths, and a path that is not in the object is TS2345.

At a glance

Use JSDoc in a .js file TypeScript in a .ts file
An object const ROUTES = /** @type {const} */ ({ home: "/", cart: "/cart" }); const ROUTES = { home: "/", cart: "/cart" } as const;
An array const SIZES = /** @type {const} */ (["S", "M", "L"]); const SIZES = ["S", "M", "L"] as const;

Examples

routes.js routes.ts Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: routes.js(16,4): error TS2345: Argument of type '"/checkout"' is not assignable to parameter of type 'Path'. routes.ts(15,4): error TS2345: Argument of type '"/checkout"' is not assignable to parameter of type 'Path'. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. routes.js(16,4): error TS2345: Argument of type '"/checkout"' is not assignable to parameter of type 'Path'. routes.ts(15,4): error TS2345: Argument of type '"/checkout"' is not assignable to parameter of type 'Path'. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. routes.js(16,4): error TS2345: Argument of type '"/checkout"' is not assignable to parameter of type 'Path'. routes.ts(15,4): error TS2345: Argument of type '"/checkout"' is not assignable to parameter of type 'Path'. checked 21 October 2026
export const ROUTES = /** @type {const} */ ({
  home: "/",
  cart: "/cart",
  account: "/account",
});

/** @typedef {(typeof ROUTES)[keyof typeof ROUTES]} Path */

/** @param {Path} path */
export function go(path) {
  location.assign(path);
}

go(ROUTES.cart);
go("/checkout");error TS2345: Argument of type '"/checkout"' is not assignable to parameter of type 'Path'.
export const ROUTES = {
  home: "/",
  cart: "/cart",
  account: "/account",
} as const;

type Path = (typeof ROUTES)[keyof typeof ROUTES];

export function go(path: Path) {
  location.assign(path);
}

go(ROUTES.cart);
go("/checkout");error TS2345: Argument of type '"/checkout"' is not assignable to parameter of type 'Path'.
/** @type {const} */ keeps literal values as their own types.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}
routes.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: routes.js(4,8): error TS2540: Cannot assign to 'cart' because it is a read-only property. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. routes.js(4,8): error TS2540: Cannot assign to 'cart' because it is a read-only property. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. routes.js(4,8): error TS2540: Cannot assign to 'cart' because it is a read-only property. checked 21 October 2026
const ROUTES = /** @type {const} */ ({ home: "/", cart: "/cart" });

ROUTES.cart = "/basket";error TS2540: Cannot assign to 'cart' because it is a read-only property.

export { ROUTES };
A const-asserted object cannot be changed.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}
point.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: point.js(12,20): error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'readonly [number, number]'. Target requires 2 element(s) but source may have fewer. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. point.js(12,20): error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'readonly [number, number]'. Target requires 2 element(s) but source may have fewer. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. point.js(12,20): error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'readonly [number, number]'. Target requires 2 element(s) but source may have fewer. checked 21 October 2026
const origin = /** @type {const} */ ([0, 0]);

/** @param {readonly [number, number]} point */
export function distanceFromOrigin([x, y]) {
  return Math.hypot(x, y);
}

distanceFromOrigin(origin);

const loose = [0, 0];
distanceFromOrigin(loose);error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'readonly [number, number]'.
  Target requires 2 element(s) but source may have fewer.
A const array is a read-only tuple.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}
routes.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: routes.js(2,48): error TS8016: Type assertion expressions can only be used in TypeScript files. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. routes.js(2,48): error TS8016: Type assertion expressions can only be used in TypeScript files. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. routes.js(2,48): error TS8016: Type assertion expressions can only be used in TypeScript files. checked 21 October 2026
const ROUTES = { home: "/", cart: "/cart" } as const;error TS8016: Type assertion expressions can only be used in TypeScript files.

export { ROUTES };
as const is TypeScript syntax.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}

What changes

Without the assertion, { home: "/" } is typed { home: string }, because object properties are mutable. With it, the type is { readonly home: "/" }: assigning to ROUTES.cart is TS2540, and the literal can be used where a union of literals is expected.

An array becomes a read-only tuple: [0, 0] is readonly [0, 0], which fits a readonly [number, number] parameter where a plain number[] does not (TS2345 in the third example).

Not a freeze

A const assertion changes types only. The object can still be modified at run time by code that ignores the types; wrap it in Object.freeze as well if that matters.

Gotchas

  • The parentheses are required, as with every JSDoc cast.
  • as const itself is TypeScript syntax: in a .js file it is TS8016.
  • Not to be confused with the @const tag, which TypeScript ignores.

Questions

How do I write as const in JavaScript?

/** @type {const} */ (value), with the parentheses. It works since TypeScript 4.5.

Sources

Last reviewed 20 October 2026.