TypeScript Variables
A TypeScript variable associates a name with a value. The variable can have an explicit type annotation, or TypeScript can infer its type from the assigned value. Variables are declared with const, let, or the older var keyword.
Use const when the variable will not be reassigned. Use let when reassignment is required. Modern TypeScript code generally avoids var because its function-scoping and hoisting behavior can produce unexpected results.
TypeScript variable declaration syntax
The following legacy syntax shows the parts of a variable declaration made with var:
var <identifier> [: type-annotation] [= value] ;
varis the declaration keyword in this syntax. In new code, preferletorconst.<identifier>is the variable name.- The type annotation follows a colon and is optional when TypeScript can infer the type.
- The initializer follows the assignment operator and is optional for
letandvar. - A semicolon can terminate the statement. JavaScript automatic semicolon insertion makes it syntactically optional in many cases, but a project should follow one consistent formatting convention.
These are the main forms of TypeScript variable declarations:
let variableName: Type;
let variableName: Type = value;
let variableName = value;
const constantName: Type = value;
const constantName = value;
A const declaration must have an initializer. A let declaration can be made without an initial value, although specifying its type is usually helpful in that situation.
Declaring TypeScript variables with let, const, and var
The declaration keyword controls whether a name can be reassigned and which scope rules apply.
| Keyword | Scope | Reassignment | Redeclaration in the same scope | Recommended use |
|---|---|---|---|---|
const | Block | No | No | Default choice for a binding that will not be reassigned |
let | Block | Yes | No | Counters, state changes, and values assigned later |
var | Function or global | Yes | Yes | Primarily existing or legacy JavaScript-compatible code |
const applicationName: string = "Order Tracker";
let pendingOrders: number = 4;
pendingOrders = 5;
var legacyStatus: string = "open";
legacyStatus = "closed";
Reassigning applicationName would cause a compile-time error because it was declared with const. Both pendingOrders and legacyStatus can receive new values compatible with their declared types.
Type annotations and inferred variable types
A type annotation explicitly states which values a variable may hold. Type inference allows the compiler to determine that type from an initializer.
let quantity: number = 12; // explicit number annotation
let productName = "Notebook"; // inferred as string
const available = true; // inferred as the literal type true
quantity = 15;
productName = "Marker";
Adding an annotation is useful when a declaration has no initializer, when the intended type is broader than the initial value, or when the annotation makes an API boundary easier to understand. Repeating an obvious inferred type is usually unnecessary.
Declaring a TypeScript variable without a value
A variable declared without an initializer initially has the runtime value undefined. Give it an explicit type when a later assignment is expected:
let customerName: string;
customerName = "Mira";
let selectedId: number | undefined;
selectedId = 108;
selectedId = undefined;
With strict null checking enabled, include undefined in the type only when the variable is intentionally allowed to return to that state. A variable must also be assigned before it is read on every relevant control-flow path.
Using union types when a variable accepts multiple value types
A union type lists the permitted alternatives. This is safer than using any because TypeScript still checks assignments and requires appropriate narrowing before type-specific operations.
let reference: string | number;
reference = "INV-204";
reference = 204;
// reference = true; // Error: boolean is not assignable
Rules for TypeScript variable names
- A variable name can contain letters, digits, underscores, and dollar signs.
- The first character cannot be a digit.
- Spaces and punctuation such as
#,@, and-cannot appear in an unquoted identifier. - Reserved language keywords cannot be used as variable names.
- Variable names are case-sensitive, so
totalandTotalidentify different bindings. - Use descriptive camelCase names such as
invoiceTotalorisPaymentCompletefor ordinary variables.
name, a1, a2, and ght6$ are valid identifiers, although descriptive names are preferable in production code.
34shf, sdf#lsk, and num@ are invalid identifiers.
Block, function, module, and class variable scope
Scope is the region of code in which a variable name can be accessed. TypeScript follows JavaScript scope rules and adds compile-time checking.
- Block scope: A
letorconstvariable declared inside braces is available only within that block. Blocks include functions, loops, and an if block. - Function scope: A variable declared with
varis available throughout its containing function, even when its declaration appears inside a nested block. - Module scope: A top-level variable in a file containing an
importorexportbelongs to that module rather than automatically becoming a global variable. - Global scope: A true global variable is accessible through the global environment. Globals should be limited because unrelated code can read or modify shared state.
- Class scope: Instance and static fields are class members. Their accessibility can also be controlled with modifiers such as
public,protected, andprivate.
function calculateTotal(prices: number[]): number {
let total = 0;
for (const price of prices) {
const tax = price * 0.05;
total += price + tax;
}
// price and tax are not available here
return total;
}
Why var behaves differently inside a block
The var keyword does not create block-scoped variables. Its declaration is processed at the beginning of the containing function, while its assignment remains in its original position. This behavior is commonly described as hoisting.
function showScope(): void {
if (true) {
var oldMessage = "Visible throughout the function";
let blockMessage = "Visible only in this block";
}
console.log(oldMessage);
// console.log(blockMessage); // Error: cannot find name
}
Both let and const are also bound to their block before the declaration line, but they cannot be accessed before initialization. This period is commonly called the temporal dead zone.
TypeScript static class variables
A static field belongs to the class itself rather than to each class instance. Access it through the class name. An instance field, by comparison, stores a separate value for each object.
var n1:number = 569 // global variable
class Person {
name:string //class variable
static sval = 10 //static property
printSomething():void {
var message:string = 'hello!' //local variable
}
}
In this example, Person.sval accesses the static field. The name field belongs to an individual Person instance, and message is local to printSomething().
Const variables and mutable objects
const prevents reassignment of the variable binding; it does not automatically make an object or array immutable. Properties and elements can still change when their types permit modification.
const settings = {
theme: "light",
notifications: true
};
settings.theme = "dark"; // Allowed
// settings = {}; // Error: reassignment is not allowed
const codes: string[] = ["A1"];
codes.push("B2"); // Allowed
Use readonly, readonly array types, or an immutable data design when object contents must not be modified through a particular type.
Using TypeScript variables inside strings
Template literals insert variable values into strings with ${...}. They use backticks instead of single or double quotation marks.
const userName = "Anika";
const completedTasks = 6;
const summary = `${userName} completed ${completedTasks} tasks.`;
console.log(summary);
Anika completed 6 tasks.
Common TypeScript variable declaration errors
- Assigning the wrong type: A variable inferred or annotated as
numbercannot later receive a string. - Reading before assignment: Ensure that every control-flow path initializes a variable before its value is used.
- Reassigning a const binding: Change the declaration to
letonly when reassignment is part of the intended design. - Assuming const makes an object immutable: It protects the binding, not every property inside the value.
- Using var in loops or conditional blocks: Its function scope may expose the variable outside the expected block.
- Using any unnecessarily: Prefer a specific type, a union, or
unknownso that the compiler can continue checking the value.
TypeScript variables FAQ
Should I use let, const, or var in TypeScript?
Use const by default and change it to let when the variable must be reassigned. Reserve var for situations where its function-scoped behavior is specifically required or when maintaining existing code that already uses it.
How do I declare a TypeScript variable with a type?
Place a colon and the type after the variable name, as in let count: number = 1. The initializer can be omitted from a let declaration, for example let count: number, but the variable must be assigned before it is read.
Can a TypeScript variable hold more than one type?
Yes. Declare a union such as let id: string | number. The variable can then hold either listed type, and TypeScript can narrow the union after checks such as typeof id === "string".
What is the difference between == and === in TypeScript?
The == operator can convert operand types before comparison, while === compares without implicit type coercion. TypeScript code generally uses === and !== because their results are easier to reason about. These operators compare values; they do not declare variables or assign new values.
TypeScript variables editorial QA checklist
- Confirm that each example uses
constwhen reassignment is unnecessary andletwhen a value changes. - Compile the examples with strict TypeScript checking and verify that intentionally invalid lines remain commented.
- Check that every uninitialized variable has an appropriate explicit type and is assigned before use.
- Verify that scope explanations distinguish block-scoped
let/constfrom function-scopedvar. - Confirm that the static-field example is accessed through the class name and is not described as an instance variable.
Summary of TypeScript variable declarations
TypeScript variables combine JavaScript declarations with compile-time type checking. Prefer const for bindings that remain assigned to the same value and let for values that change. Allow inference when the initializer makes the type clear, and add annotations when declaring a variable without a value or defining a deliberate type boundary. For more language topics, continue with the TypeScript Tutorial.
TutorialKart.com