ProgrammingFrontend Developer

Explain the difference between variable declarations using let, const, and var in TypeScript. How does the choice of each affect scope, the ability to redeclare, mutability of values, and error prevention? Provide examples of typical usage scenarios for each declaration method.

Pass interviews with Hintsage AI assistant

Answer.

In TypeScript (as well as modern JavaScript), variables can be declared using let, const, and var, and there are important differences between them:

  • let — Block-scoped, the variable can be reassigned (assigned a new value), but cannot be redeclared in the same scope.
  • const — Also block-scoped, a value must be assigned immediately, cannot be reassigned (but internal properties of an object declared with const are mutable!).
  • var — Function-scoped, hoisting is possible, the variable can be redeclared and changed.

Example:

if (true) { let a = 10; const b = 20; var c = 30; } console.log(c); // 30 — visible outside the block! console.log(a); // Error: a is not defined console.log(b); // Error: b is not defined

Typical scenarios:

  • const — for values that should not change (constants, configurations, function references).
  • let — for values that change during execution (counters, loop variables).
  • var — not recommended, only for legacy code support.

Trick question.

Can const make an object completely immutable? Explain and provide an example.

Answer: No, const only prevents the change of the actual reference, but does not protect against changes to the object's properties!

const obj = { x: 1 }; obj.x = 2; // This is allowed! obj = { x: 3 }; // Error: assigning a new reference

For complete immutability, Object.freeze is used:

const frozen = Object.freeze({ x: 1 }); frozen.x = 2; // Error in strict mode, but the compiler doesn't always warn!

Examples of real errors due to ignorance of the topic nuances.


Story

During the migration of a large frontend project to TypeScript, developers massively replaced var with let, not realizing that the scope is now block-scoped. This led to the fact that counters in some for loops were not accessible outside the loop, causing unexpected errors in logic: the code stopped working when trying to access the loop counter after the loop completed.


Story

A developer declared a constant using const to store a configuration object, believing that the properties were protected from changes. Later, in runtime, another part of the program changed a property: this caused hard-to-trace errors in data processing because external code "unexpectedly" changed global settings for all users.


Story

In a project, let, const, and var were used simultaneously without a clear policy. One component redeclared a var variable within a function, while another part expected the variable to be declared with let and thus would not be visible outside the block. The result: variable overlaps, failures in internal logic, and difficult debugging issues with an unclear variable lifecycle.