In TypeScript (as well as modern JavaScript), variables can be declared using let, const, and var, and there are important differences between them:
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.Can
constmake 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!
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.