A variable is the storage location, which is used to store value/information to be referenced and used by programs. It acts as a container for value in code and must be declared before the use. We can declare a variable by using the var keyword. In TypeScript, the variable follows the same naming rule as of JavaScript variable declaration. These rules are-
- The variable name must be an alphabet or numeric digits .
- The variable name cannot start with digits.
- The variable name cannot contain spaces and special character , except the u nderscore(_) and the dollar($) sign.
In ES6, variables can be declared using the keywords let and const. While these variables share a similar syntax for both declaration and initialization, they differ in terms of scope and application. In TypeScript, it is generally advised to use the let keyword for variable definition, as it offers enhanced type safety.
The let keyword shares similarities with the var keyword in certain aspects, while const is essentially a variant of let that disallows any re-assignment to a variable.
Variable Declaration
A variable can be defined using one of four methods:
- Specify the type and value simultaneously in a single declaration.
- Declare a variable without assigning a value. Consequently, the variable will be initialized to undefined.
- Assign a value without specifying its type. Consequently, the variable will be defined as any.
- Declare without specifying a value or type. Consequently, the variable will be assigned the type any and initialized to undefined.
var [identifier] : [type-annotation] = value;
var [identifier] : [type-annotation];
var [identifier] = value;
var [identifier];
Let us examine each of the three variable keywords individually.
var keyword
Typically, the var keyword is employed to define a variable in JavaScript.
var x = 50;
A variable can also be defined within the function:
function a() {
var msg = " Welcome to TypeScript Tutorial !! ";
return msg;
}
a();
It is also possible to access a variable from one function within another function:
function a() {
var x = 50;
return function b() {
var y = x+5;
return y;
}
}
var b = a();
b(); //returns '55'
Scoping rules
Programmers coming from different languages may encounter unusual scoping rules regarding variable declaration in JavaScript. In TypeScript, variables defined using the var keyword possess function scope. Such variables have global visibility within the function in which they are declared. Additionally, they can be accessed by any other functions that are within the same scope.
Example
function f()
{
var X = 5; //Available globally inside f()
if(true)
{
var Y = 10; //Available globally inside f()
console.log(X); //Output 5
console.log(Y); //Output 10
}
console.log(X); //Output 5
console.log(Y); //Output 10
}
f();
console.log(X); //Returns undefined because value cannot accesses from outside function
console.log(Y); //Returns undefined because value cannot accesses from outside function
NOTE: As var declarations are accessible anywhere within their containing module, function, global scope, or namespace, some people call this var-scoping or function-scoping. Parameters are also called function scoped.
let declarations
The let keyword functions similarly to the var keyword. However, the var declaration presents certain issues in programming, which led to the introduction of the let keyword in ES6 for declaring variables in TypeScript and JavaScript. In contrast to the var keyword, the let keyword imposes specific restrictions on scope.
The let keyword can improve the clarity of our code and reduce the likelihood of programming mistakes.
The syntax for let statements is identical to that of var statements:
var declaration: var b = 50;
let declaration: let b = 50;
The primary distinction between var and let lies not in the syntax but in their semantics. Variables declared using the let keyword are confined to the nearest surrounding block, which may be smaller than a function block.
Block Scoping
A variable defined with the let keyword employs block scoping or lexical scoping. In contrast to variables declared with the var keyword, which can spill over into their enclosing function's scope, a block-scoped variable remains inaccessible outside of its defining block.
function f(input: boolean) {
let x = 100;
if (input) {
// "x" exists here
let y = x + 1;
return y;
}
// Error: "y" doesn't exist here
return y;
}
In this instance, we define two local variables, x and y. The scope of x is confined to the function f's body, whereas the scope of y is restricted to the block of the enclosing if statement.
NOTE- The variables declared in a try-catch clause also have similar scoping rules. For example:
try {
throw "Hi!!";
}catch (e) {
console.log("Hello");
}
// 'e' doesn't exist here, so error will found
console.log(e);
Re-declaration and Shadowing
Using the var keyword for variable declarations meant that the number of times we declared a variable was irrelevant; we would end up with just one instance. In the example below, every declaration of x points to the same variable x, which is entirely permissible. However, there is an issue that can be identified when using the let keyword for declarations.
Example without let keyword:
function f(a) {
var a;
var a;
if (true) {
var a;
}
}
Example with let keyword:
let a = 10;
let a = 20; // it gives error: can't re-declare 'a' in the same scope
Shadowing refers to the process of introducing a new identifier within a more nested scope, which has already been defined in an outer scope. While this practice is not inherently wrong, it can lead to confusion. The outer identifier becomes inaccessible within the loop where the loop variable is shadowing it. This can potentially introduce errors due to unintentional shadowing, but it can also assist in safeguarding the application against specific bugs.
Example
var currencySymbol = "$";
function showMoney(amount) {
var currencySymbol = "€";
document.write(currencySymbol + amount);
}
showMoney("100");
In the example provided, a global variable is defined with the same name as that of the inner method. The inner variable is utilized solely within that specific function, while all other functions will reference the global variable declaration.
In coding, shadowing is generally discouraged to promote greater clarity. However, in certain situations where it may be appropriate to utilize it, we should apply it judiciously.
Hoisting
Hoisting of var
Hoisting is a feature of JavaScript. In this process, variable and function declarations are relocated to the top of their respective scope prior to the execution of the code. This can be illustrated through the following example.
Note: Hoisting does not happen if we initialize the variable.
Example
function get(x){
console.log(a); //printing x variable. Value is undefined
//declared variable after console hoisted to the top at run time
var a = x;
//again printing x variable. Value is 3.
console.log(a);
}
get(4);
Output:
undefined
4
Hoisting of let
A variable that is declared using the let keyword does not undergo hoisting. Attempting to access a let variable prior to its declaration will lead to a ReferenceError.
Example
{
//program doesn't know about variable b so it will give me an error.
console.log(b); // ReferenceError: b is not defined
let b = 3;
}
const declarations
The const keyword is utilized to declare an immutable value that cannot be altered subsequently. It maintains a constant value. The const declaration adheres to the same scoping principles as the let declaration; however, it does not permit re-assignment of a new value.
Note: According to the naming standards, the const variable must be declared in capital letters. Naming standards should be followed to maintain the code for the long run.
Example
function constTest(){
const VAR = 10;
console.log("Value is: " +VAR);
}
constTest();
Output:
Value is: 10
What will happen when we try to re-assign the const variable?
Attempting to reassign a previously defined const variable in code will result in an error. Therefore, it is not possible to assign a new value to an already established const variable.
Example
function constTest(){
const VAR = 10;
console.log("Output: " +VAR); // Output: 10
const VAR = 10;
console.log("Output: " +VAR); //Uncaught TypeError: Assignment to constant variable
}
constTest();
Output:
SyntaxError: Identifier 'VAR' has already been declared.