Skip to content
Theory · Annotations and type inference · lesson 8 of 9

const and mutable objects

A sealed const jar holds one value, and TypeScript labels it exactly. With a number everything is clear: const limit = 5 stays five forever. But what if the constant holds an object?

TypeScript
const cart = { total: 0 };
const scores = [3, 5];
cart.total = 1500;
scores.push(4);
console.log(cart.total, scores.length); // 1500 3

The program compiles without errors and prints 1500 3. Let's go through it line by line:

  1. const cart = { total: 0 };—the constant cart holds an object with the property total.
  2. const scores = [3, 5];—the constant scores holds an array of two numbers.
  3. cart.total = 1500; changes a property inside the object, and tsc does not object.
  4. scores.push(4); adds an element to the same array—again with no error.
  5. console.log prints 1500 3: total now holds 1500, and the array has three elements.

The object and the array changed, although both are declared with const. So what does const forbid?

What const forbids

const forbids giving the name a new value—writing another object into cart, even one of exactly the same shape:

TypeScript
const cart = { total: 0 };
cart = { total: 1500 }; // ✗
TEXT
error TS2588: Cannot assign to 'cart' because it is a constant.

The message means: "you cannot give cart a new value because it is a constant". In JavaScript this line would fail only at run time, with the error TypeError: Assignment to constant variable. TypeScript finds it earlier—at compile time.

What can change inside

A constant holds the same value all the time—the same object or array. What lies inside it, const does not guard:

  • an object's properties: cart.total = 1500;
  • an array's elements: scores[0] = 10;
  • methods that change an array: scores.push(4).

This is where the sealed-jar analogy ends: it holds for numbers and strings, which have no parts. An object is more like a chest of drawers. const glues the label cart firmly to one chest, but its drawers still slide out.

Interviewers often ask: "Can you change an object declared with const?" The answer: its properties, yes; writing another object into the name, no.

Property types stay general

You have already seen that const point = { x: 5 } gets the type { x: number; }. The same goes for cart: its type is { total: number; }. So the property takes any other number, but not a value of another type:

TypeScript
const cart = { total: 0 };
cart.total = "бесплатно"; // ✗
TEXT
error TS2322: Type 'string' is not assignable to type 'number'.

const does not guard the object's contents, but the type does: total can change, but only to a number.

Common mistake

Declaring with const a value that later changes as a whole, such as a counter:

TypeScript
const attempts = 0;
attempts = attempts + 1; // ✗
TEXT
error TS2588: Cannot assign to 'attempts' because it is a constant.

attempts + 1 is a new number, and it can be written into the name only if the name is declared with let. The fix is let attempts = 0;. The rule for choosing is the same as in JavaScript: const by default, let when the name will get a new value.

Key points

  • const forbids giving the name a new value: cart = … is error TS2588.
  • The contents of an object or array in a const can change: properties, elements, push.
  • Property types are inferred as general: cart.total of type number takes another number, but not a string.
  • A value that changes as a whole, such as a counter, needs let.