TypeScript Variables, Types and Enums in 2025: let/const, Type Inference, Enums & Best Practices
1. How do you declare variables with let and const in TypeScript?
Q: Differences between let, const, and var in TypeScript
Variables in TypeScript are declared using let, const, or var (less common). TypeScript adds static typing to JavaScript’s variable declarations.
- let: Declares a block-scoped variable that can be reassigned.
- Syntax:
let variableName: type = value;. - const: Declares a block-scoped constant that cannot be reassigned after initialization.
- Syntax:
const variableName: type = value;. - var: Avoided in modern TypeScript due to function-scoping and hoisting issues.
Use Case: Use let for variables that change; const for immutable values (though object properties can still be modified).
Can you give an example of let and const in TypeScript?
// Declaring variables with let and const
let counter: number = 0;
counter = 10; // Reassignment allowed
console.log(`Counter: ${counter}`); const maxAttempts: number = 3;
// maxAttempts = 5; // Error: Cannot assign to 'maxAttempts' because it is a constant const config: { host: string; port: number } = { host: "localhost", port: 8080 };
config.port = 3000; // Allowed: Modifying object property
console.log(`Config: ${JSON.stringify(config)}`); Output:
Counter: 10
Config: {"host":"localhost","port":3000} 2. What are type inference and explicit typing in TypeScript?
Q: When to use inference vs explicit annotations
Type Inference: TypeScript automatically infers a variable’s type based on its initial value, reducing the need for explicit type annotations.
- Example:
let x = 42;infersx: number. - When It Works: Clear initial values (e.g., numbers, strings, arrays).
- Limitations: May infer
anyin ambiguous cases, reducing type safety.
Explicit Typing: Manually specifying a variable’s type using type annotations.
- Syntax:
let variableName: type = value;. - When to Use: Complex types, ensuring clarity, or preventing
any.
Use Case: Use inference for simple cases; explicit typing for complex or ambiguous cases.
Can you give an example of type inference vs. explicit typing?
// Type inference vs. explicit typing
// Type inference
let name = "kristal"; // Inferred as string
let count = 42; // Inferred as number
let scores = [1, 2, 3]; // Inferred as number[] // Explicit typing
let username: string = "Sashi";
let attempts: number = 5;
let settings: { theme: string; darkMode: boolean } = { theme: "light", darkMode: false }; // Type inference limitation
let value = true; // Inferred as boolean
// value = "test"; // Error: Type 'string' is not assignable to type 'boolean' // Explicit typing for clarity
let data: any = 123; // Explicit any (avoid when possible)
data = "now a string"; // No error due to any console.log(`Name: ${name}, Count: ${count}, Scores: ${scores}`);
console.log(`Username: ${username}, Attempts: ${attempts}, Settings: ${JSON.stringify(settings)}`);
console.log(`Data: ${data}`); Output:
Name: kristal, Count: 42, Scores: 1,2,3
Username: Sashi, Attempts: 5, Settings: {"theme":"light","darkMode":false}
Data: now a string 3. What are enums in TypeScript?
Q: Numeric, string, and const enums explained
Enums define a set of named constants, either numeric or string-based, to represent a fixed set of values.
- Syntax:
enum EnumName { Member1, Member2, Member3 } - Types:
- Numeric enums: Default to 0-based indices (customizable).
- String enums: Explicit string values for each member.
- Const enums: Optimized at compile-time, removed from output JavaScript.
- Use Case: Representing fixed sets of values (e.g., roles, statuses, days).
- Access: Use
EnumName.Memberto access values.
Can you give an example of working with enums?
// Working with enums
// Numeric enum
enum Role { User, // 0 Admin, // 1 Guest = 5 // Custom value
} // String enum
enum Status { Pending = "PENDING", Approved = "APPROVED", Rejected = "REJECTED"
} // Const enum
const enum Direction { Up, Down, Left, Right
} // Usage
let userRole: Role = Role.Admin;
let userStatus: Status = Status.Approved;
let move: Direction = Direction.Up; console.log(`Role: ${userRole} (${Role[userRole]})`);
console.log(`Status: ${userStatus}`);
console.log(`Direction: ${move}`); // Note: Direction is inlined in output JS // Enum in function
function getAccessLevel(role: Role): string { switch (role) { case Role.Admin: return "Full access"; case Role.User: return "Limited access"; case Role.Guest: return "View-only access"; default: return "Unknown"; }
} console.log(`Access: ${getAccessLevel(Role.User)}`); Output:
Role: 1 (Admin)
Status: APPROVED
Direction: 0
Access: Limited access 4. Can you provide a comprehensive example of variables, types, and enums in TypeScript?
Q: Full beginner example combining let/const, inference, and enums
Project Structure:
ts-variables-enums/
├── src/
│ └── main.ts
├── tsconfig.json
└── package.json main.ts:
// Comprehensive example with let, const, types, and enums
// Enum for user roles
enum Role { Employee = "EMPLOYEE", Manager = "MANAGER", Contractor = "CONTRACTOR"
} // Interface for type safety
interface Employee { name: string; role: Role; salary: number;
} // Variables with let and const
let department: string = "IT"; // Inferred as string
const maxSalary: number = 100000; // Explicit number type // Function with type inference and explicit typing
function promoteEmployee(emp: Employee): Employee { let newSalary: number = emp.salary * 1.1; // Explicit typing if (newSalary > maxSalary) { newSalary = maxSalary; } const updatedEmployee = { // Inferred as Employee ...emp, salary: newSalary, role: emp.role === Role.Employee ? Role.Manager : emp.role }; return updatedEmployee;
} // Usage
const employee: Employee = { name: "kristal", role: Role.Employee, salary: 60000
}; const promoted = promoteEmployee(employee);
console.log(`Department: ${department}`);
console.log(`Promoted Employee: ${JSON.stringify(promoted)}`);
console.log(`Role: ${promoted.role}`); package.json:
{ "name": "ts-variables-enums", "version": "1.0.0", "scripts": { "start": "tsc && node dist/main.js", "build": "tsc", "watch": "tsc --watch" }, "devDependencies": { "typescript": "^5.6.2" }
} tsconfig.json:
{ "compilerOptions": { "target": "ES2020", "module": "NodeNext", "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true, "skipLibCheck": true }, "include": ["src/**/*"], "exclude": ["node_modules"]
} Steps to Run:
- Create the project structure.
- Install dependencies:
npm install. - Compile:
npm run build. - Run:
npm start.
Output:
Department: IT
Promoted Employee: {"name":"kristal","role":"MANAGER","salary":66000}
Role: MANAGER Description:
- Variables:
let departmentuses type inference;const maxSalaryuses explicit typing;const updatedEmployeeinfersEmployeetype. - Type Inference/Explicit Typing: Used in
newSalary(explicit) andupdatedEmployee(inferred). - Enums:
Rolestring enum ensures type-safe role assignments. - Interfaces:
Employeeenforces structure for employee data.
5. What are common mistakes in TypeScript variables, types, and enums?
Q: Beginner pitfalls to avoid
- Variables (let/const):
- Overusing
varinstead oflet/const, causing scoping issues. - Reassigning
constvariables or assumingconstobjects are immutable.
- Overusing
- Type Inference/Explicit Typing:
- Relying on
anytype, reducing type safety. - Overusing explicit typing when inference is sufficient, cluttering code.
- Relying on
- Enums:
- Using numeric enums without understanding default indexing.
- Not using
const enumfor compile-time optimization when runtime enum objects are unnecessary.
- General:
- Not leveraging TypeScript’s type system for complex data structures.
- Ignoring compiler errors, leading to runtime issues.
6. What are best practices for TypeScript variables, types, and enums?
Q: Recommended practices for clean code in 2025
- Variables (let/const):
- Use
letfor variables that change;constfor immutable bindings. - Avoid
varto prevent scoping issues. - Use
constfor objects/arrays when the reference won’t change.
- Use
- Type Inference/Explicit Typing:
- Leverage type inference for simple cases (e.g.,
let x = 42). - Use explicit typing for complex types or public APIs (e.g., function parameters).
- Avoid
anyunless absolutely necessary; useunknownfor safer dynamic typing.
- Leverage type inference for simple cases (e.g.,
- Enums:
- Use string enums for readability or when values are used as strings.
- Use
const enumfor performance in compile-time scenarios. - Define enums for fixed sets of values to improve type safety.
- General:
- Follow TypeScript naming conventions: camelCase for variables, PascalCase for types/enums.
- Use interfaces or types for complex data structures.
- Enable
strictmode (strict: trueintsconfig.json) for better type checking. - Test edge cases (e.g., invalid types, enum mismatches).
- Use tools like
tscand linters (e.g.,eslint) to catch errors.