Skip to content

Variables

In TypeScript, let declares a mutable binding and const declares an immutable one. Rust flips the default: let is immutable by default, and you opt into mutability with let mut. Rust’s const is similar to TypeScript’s — a compile-time constant with a required type annotation.

Rust infers types just like TypeScript. You can annotate explicitly when you need clarity or when the compiler cannot infer the type on its own.

// TypeScript
let score: number = 42;
let name = "Alice"; // inferred as string
// Rust
let score: i32 = 42;
let name = "Alice"; // inferred as &str

Rust allows you to re-declare a variable with let in the same scope — this is called shadowing. The new binding replaces the old one. This differs from mutation: you can even change the type. TypeScript does not allow re-declaring the same name with let in the same scope.

TypeScript
// TypeScript: cannot shadow with let in same scope
const x = 5;
// let x = x + 1; // SyntaxError
// Workaround: use a new name or use let + reassign
let count = 5;
count = count + 1;
console.log(count); // 6
Rust
fn main() {
let x = 5;
// x = 6; // ERROR: cannot assign twice to immutable variable
let x = x + 1; // shadowing: a new binding named x
println!("{x}"); // 6
let mut y = 10; // explicitly mutable
y += 5;
println!("{y}"); // 15
const MAX_POINTS: u32 = 100_000; // compile-time constant
println!("{MAX_POINTS}");
}
fn main() {
let x = 5;
println!("x = {x}");
let x = x + 1;
println!("after shadowing, x = {x}");
let mut y = 10;
y += 5;
println!("mutable y = {y}");
const MAX_POINTS: u32 = 100_000;
println!("const MAX_POINTS = {MAX_POINTS}");
}
What does `let x = 5;` create in Rust?
Which keyword do you use to allow reassignment of a variable in Rust?
What is shadowing in Rust?