Rust for JavaScript Developers: Getting Started Guide
Tech Setup1 min read
TS
Tech Setup
Reviewed July 29, 2026
Why Rust?
Rust gives you the performance of C++ with memory safety guarantees — no garbage collector, no null pointer exceptions, no data races. If you write Node.js services that need raw speed or CLI tools, Rust is worth learning.
Installation
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Verify
rustc --version
cargo --version
Hello World
cargo new hello-rust
cd hello-rust
cargo run
This creates:
hello-rust/
├── Cargo.toml # like package.json
└── src/
└── main.rs # like index.js
Concept Mapping
| JavaScript | Rust |
|---|---|
const x = 5 | let x = 5 |
let x = 5 (mutable) | let mut x = 5 |
function add(a, b) | fn add(a: i32, b: i32) -> i32 |
const arr = [1, 2] | let arr = vec![1, 2] |
arr.push(3) | arr.push(3) |
obj.name | obj.name (struct) or obj["name"] (HashMap) |
null / undefined | Option<T> (None or Some(val)) |
throw Error() | Result<T, E> (Err()) |
try { } catch { } | match result { Ok(v) => ..., Err(e) => ... } |
Variables and Mutability
fn main() {
let x = 5; // immutable (like const)
let mut y = 10; // mutable (like let)
y += 1; // OK
// x += 1; // ERROR: cannot mutate
}
Ownership (The Big Concept)
Rust's ownership system replaces garbage collection. Every value has exactly one owner:
fn main() {
let s1 = String::from("hello");
let s2 = s1; // s1 is MOVED to s2
// println!("{}", s1); // ERROR: s1 no longer valid
println!("{}", s2); // OK
}
Borrowing (like passing by reference)
fn print_length(s: &String) { // borrow, don't take ownership
println!("{}", s.len());
}
fn main() {
let s = String::from("hello");
print_length(&s); // pass reference
println!("{}", s); // still valid
}
Option and Result
Option (replaces null)
fn find_user(id: u32) -> Option<String> {
if id == 1 {
Some(String::from("Alice"))
} else {
None
}
}
fn main() {
match find_user(1) {
Some(name) => println!("Found: {}", name),
None => println!("Not found"),
}
// Or use unwrap (panics on None)
let name = find_user(1).unwrap();
}
Result (replaces try/catch)
use std::fs;
fn main() {
match fs::read_to_string("config.json") {
Ok(content) => println!("Config: {}", content),
Err(e) => println!("Error reading file: {}", e),
}
// Or use ? operator in functions that return Result
}
Structs (like classes/objects)
struct User {
name: String,
email: String,
active: bool,
}
impl User {
fn new(name: &str, email: &str) -> User {
User {
name: name.to_string(),
email: email.to_string(),
active: true,
}
}
fn greet(&self) -> String {
format!("Hi, I'm {}", self.name)
}
}
fn main() {
let user = User::new("Alice", "alice@example.com");
println!("{}", user.greet());
}
Vectors (like arrays)
fn main() {
let mut nums = vec![1, 2, 3];
nums.push(4);
// Iterate
for n in &nums {
println!("{}", n);
}
// Map + collect
let doubled: Vec<i32> = nums.iter().map(|n| n * 2).collect();
println!("{:?}", doubled); // [2, 4, 6, 8]
}
Error Handling Pattern
use std::num::ParseIntError;
fn parse_number(s: &str) -> Result<i32, ParseIntError> {
s.parse::<i32>()
}
fn main() {
match parse_number("42") {
Ok(n) => println!("Parsed: {}", n),
Err(e) => println!("Failed: {}", e),
}
// Chaining with ?
fn compute(s: &str) -> Result<i32, ParseIntError> {
let n = parse_number(s)?;
Ok(n * 2)
}
}
Cargo Commands
| Command | What It Does |
|---|---|
cargo new name | Create new project |
cargo build | Compile (debug) |
cargo build --release | Compile (optimized) |
cargo run | Build + run |
cargo test | Run tests |
cargo clippy | Lint |
cargo fmt | Format code |
cargo add serde --features derive | Add dependency |
Learning Resources
- The Rust Book: doc.rust-lang.org/book
- Rust by Example: doc.rust-lang.org/rust-by-example
- Exercism Rust Track: exercism.org/tracks/rust
Related articles

Software Config
Mastering npm and npx in 2026: Modern Workflow Guide

Software Config
Connect Free Lovable with GitHub: Version Control Guide
Software Config