DEV Community

Jacob Asper
Jacob Asper

Posted on • Edited on

Variables in Rust - Rust for TypeScript Developers

Table Of Contents

Naming

In Rust, variables are snake cased, while constants are conventially in screaming snake case

const CONSTANT_VALUE: i32 = 2;
let non_constant_value = 32;
Enter fullscreen mode Exit fullscreen mode

Note that variables defined with const must be explicitly typed


Scope

In Rust, variables are block scoped just like variables declared with let and const in TypeScript

fn main() {
  let x = 32;
  {
    let x = 12;
    println!("{x}") // 12
  }
  println!("{x}") // 32
}
Enter fullscreen mode Exit fullscreen mode

Initialization

In TypeScript, the initialization of variables declared with var is hoisted

console.log(x); // undefined
var x = 12;
console.log(x); // 12
Enter fullscreen mode Exit fullscreen mode

The initialization of variables declared with let or const is not hoisted

console.log(x);
let x = 12;
Enter fullscreen mode Exit fullscreen mode
Uncaught ReferenceError: can't access lexical declaration 'x' before initialization
Enter fullscreen mode Exit fullscreen mode

However, they are assigned undefined if not given an initializer

let x;
console.log(x) // undefined
Enter fullscreen mode Exit fullscreen mode

Rust takes the more modern behavior of let and const and takes it one step further. Variables are not assigned a value if not given an initializer

This works

fn main() {
  let x = 12;
  println!("{x}"); // 12
}
Enter fullscreen mode Exit fullscreen mode

This does not

fn main() {
  let x: i32;
  println!("{x}");
}
Enter fullscreen mode Exit fullscreen mode
error[E0381]: used binding `x` isn't initialized
 --> src/main.rs:4:16
  |
2 |     let x: i32;
  |         - binding declared here but left uninitialized
    |
3 |     println!("{x}");
  |                ^ `x` used here but it isn't initialized
Enter fullscreen mode Exit fullscreen mode

Declaration

Variables declared with const in Rust can be global, but variables declared with let cannot

So this works,

const X: i32 = 12;

fn main() {

}
Enter fullscreen mode Exit fullscreen mode

But this does not

let x = 12;

fn main() {

}
Enter fullscreen mode Exit fullscreen mode
error: expected item, found keyword `let`
 --> src/main.rs:1:1
  |
1 | let x = 12;
  | ^^^ consider using `const` or `static` instead of `let` for global variables
Enter fullscreen mode Exit fullscreen mode

In TypeScript, variables declared with var, let, or const can be declared anywhere and aren't required to be explicitly typed

let x = 12;
Enter fullscreen mode Exit fullscreen mode

Redeclaration

In TypeScript, variables assigned with var can be redeclared locally

var x = 12;
console.log(x); // 12

var x = 32;
console.log(x); // 32
Enter fullscreen mode Exit fullscreen mode

Variables declared with let or const cannot be redeclared locally

const x = 12;
console.log(x);

const x = 32;
console.log(x);
Enter fullscreen mode Exit fullscreen mode
Cannot redeclare block-scoped variable 'x'.
Enter fullscreen mode Exit fullscreen mode

Rust's const works the same as TypeScript's in this sense

fn main() {
  const X: i32 = 12;
  const X: i32 = 12;
}
Enter fullscreen mode Exit fullscreen mode
error[E0428]: the name `X` is defined multiple times
 --> src/main.rs:5:3
  |
4 |   const X: i32 = 12;
  |   ------------------ previous definition of the value `X` here
5 |   const X: i32 = 12;
  |   ^^^^^^^^^^^^^^^^^^ `X` redefined here
  |
  = note: `X` must be defined only once in the value namespace of this block
Enter fullscreen mode Exit fullscreen mode

Rust's let works like var here—it can be redeclared in the same namespace

fn main() {
  let x = 12;
  println!("{x}"); // 12

  let x = 43;
  println!("{x}"); // 43
}
Enter fullscreen mode Exit fullscreen mode

However, variables declared with let can be redeclared with a different type!

fn main() {
  let x = 32;
  println!("{x}");

  let x = "hi";
  println!("{x}");
}
Enter fullscreen mode Exit fullscreen mode

While in TypeScript, variable declarations can't change type

var x = 1
var x = 'hi'
Enter fullscreen mode Exit fullscreen mode
Subsequent variable declarations must have the same type.
Variable 'x' must be of type 'number', but here has type 'string'.
Enter fullscreen mode Exit fullscreen mode

Reassignment

In TypeScript, variables declared with const cannot be reassigned

const x = 12;
x = 93;
Enter fullscreen mode Exit fullscreen mode
Cannot assign to 'x' because it is a constant.
Enter fullscreen mode Exit fullscreen mode

Variables declared with var or let can be reassigned

let x = 12;
console.log(x); // 12

x = 32;
console.log(x); // 32
Enter fullscreen mode Exit fullscreen mode

In Rust, variables assigned with both let and const cannot be reassigned

fn main() {
  let x = 12;

  x = 23;
}
Enter fullscreen mode Exit fullscreen mode
error[E0384]: cannot assign twice to immutable variable `x`
 --> src/main.rs:6:3
  |
4 |   let x = 12;
  |       -
  |       |
  |       first assignment to `x`
  |       help: consider making this binding mutable: `mut x`
5 |   
6 |   x = 23;
  |   ^^^^^^ cannot assign twice to immutable variable
Enter fullscreen mode Exit fullscreen mode

Mutability

As the compiler so kindly pointed out, we can use the mut keyword with let to make x mutable

fn main() {
  let mut x = 12;
  println!("{x}"); // 12

  x = 23;
  println!("{x}"); // 23
}
Enter fullscreen mode Exit fullscreen mode

This differs from TypeScript, where objects and arrays are mutable by default

const arr = [];
arr.push(1);

console.log(arr); // [1]
Enter fullscreen mode Exit fullscreen mode

In Rust, this does not compile without the mut keyword

fn main() {
  let vec = Vec::new();
  vec.push(1);
}
Enter fullscreen mode Exit fullscreen mode
error[E0596]: cannot borrow `vec` as mutable, as it is not declared as mutable
 --> src/main.rs:5:3
  |
4 |   let vec = Vec::new();
  |       --- help: consider changing this to be mutable: `mut vec`
5 |   vec.push(1);
  |   ^^^^^^^^^^^ cannot borrow as mutable
Enter fullscreen mode Exit fullscreen mode

Outro

Thank you for reading! Please let me know if you have any suggestions.

Top comments (3)

Collapse
 
20jasper profile image
Jacob Asper • Edited

Thank you for the correction, I appreciate it!

Edit: I looked into the static keyword, but couldn't find a way to both use the let and static keywords outside of the main function. Could you give me an example or explain a little more if I'm misunderstanding?

Collapse
 
wudixer profile image
Steffen Lips

Hi,
maybe it is worth to note, that in Rust a re-declaration of a variable with let can also be of a different type.

Collapse
 
20jasper profile image
Jacob Asper • Edited

Good point! And another difference from TypeScript. Thank you!

Edit: I just added your suggestion to the end of the Redeclaration section