Skip to content
>_rs4ts

JavaScript & TypeScript to Rust Cheatsheet

9 min readupdated byAhmet ZeybekAhmet Zeybek· Jul 10, 2026

A single-page lookup for the question you will ask most often while learning Rust: “what is the Rust equivalent of this JavaScript or TypeScript thing?” Each row pairs the code you already write on the left with its idiomatic Rust counterpart on the right. The mappings are deliberately terse; every section links to the full chapter where the why lives.

If you only skim one page before starting, make it this one, then keep it open in a tab.


TypeScript / JavaScriptRust
let x = 1 (reassignable)let mut x = 1;
const x = 1 (no reassign)let x = 1; (immutable by default)
const MAX = 100 (true constant)const MAX: i32 = 100;
reassign with a new typeshadowing: let x = 5; let x = "five";
numbersized: i32, i64, u32, usize, f64
bigint (arbitrary precision)i128 / u128 (fixed 128-bit; for true arbitrary precision use the num-bigint crate)
stringString (owned) and &str (borrowed)
booleanbool
null / undefinedOption<T> with None
anyno equivalent; reach for generics, an enum, or serde_json::Value
[1, 2, 3]vec![1, 2, 3] (a growable Vec<T>)
fixed-length tuple [string, number](String, i32)
{ id: 1 } objecta struct, or a HashMap for dynamic keys

See: Variables and Mutability, Basic Types, Stack vs Heap.


TypeScript / JavaScriptRust
function add(a: number, b: number): numberfn add(a: i32, b: i32) -> i32
return a + b;a + b (last expression, no return, no ;)
(x) => x + 1|x| x + 1
capturing closure () => count++move || count += 1 (see Fn/FnMut/FnOnce)
default parameter f(a = 1)no defaults; take Option<T> or use a builder
rest parameter ...argsa slice args: &[T]
void return() (the unit type)
pass a function g(f)fn g(f: impl Fn() -> T)

See: Basic Functions, Parameters, Arrow Functions vs Closures, Higher-Order Functions.


TypeScript / JavaScriptRust
cond ? a : bif cond { a } else { b } (an expression)
if (value) (truthy)if value (must be a real bool)
switch (x) { ... }match x { ... } (exhaustive, no fall-through)
for (let i = 0; i < n; i++)for i in 0..n
for (const x of arr)for x in &arr
arr.forEach(f)arr.iter().for_each(f) or a for loop
while (cond)while cond
while (true) { ... }loop { ... } (can break value)
labelled break outer'outer: loop { break 'outer; }

See: Conditionals, Match, Loops, if let / while let.


There is no null and no undefined in Rust. Absence is the None variant of Option<T>, and a failure is the Err variant of Result<T, E>. The type system makes you handle both.

TypeScript / JavaScriptRust
value ?? fallbackoption.unwrap_or(fallback)
obj?.prop (optional chaining)option.map(|o| o.prop) / .and_then(...)
if (x != null) { use(x) }if let Some(x) = option { use(x) }
throw new Error("boom")return Err(MyError::Boom)
try { ... } catch (e) { ... }match result { Ok(v) => ..., Err(e) => ... }
const v = await f() (may throw)let v = f().await?;
rethrow / propagatethe ? operator
class HttpError extends Errorenum AppError { ... } with thiserror

See: Result and Option, The ? Operator, Option Enum, Custom Errors.


Most array methods exist in Rust, but on iterators, and they are lazy: nothing runs until a consumer such as .collect(), .sum(), or a for loop pulls the values through.

TypeScript / JavaScriptRust
arr.map(f)arr.iter().map(f).collect()
arr.filter(f)arr.iter().filter(f).collect()
arr.reduce(f, init)arr.iter().fold(init, f)
arr.find(f)arr.iter().find(f) (returns Option)
arr.some(f) / arr.every(f)arr.iter().any(f) / .all(f)
arr.includes(x)arr.contains(&x)
arr.push(x) / arr.lengthvec.push(x) / vec.len()
arr.slice(a, b)&vec[a..b]
arr.sort()vec.sort()
[...a, ...b]a.iter().chain(&b).collect()
new Map() / map.get(k)HashMap::new() / map.get(&k) (returns Option)
new Set()HashSet::new()
Object.keys(o) / Object.values(o)map.keys() / map.values()
Array.from({ length: n }, ...)(0..n).map(...).collect()

See: Vectors, Iterators, Iterator Consumers, HashMaps.


TypeScript / JavaScriptRust
"hello " + nameformat!("hello {name}")
`total: ${n}` (template)format!("total: {n}")
s.length (UTF-16 code units — "🎉".length === 2)s.chars().count() (Unicode scalars) or s.len() (UTF-8 bytes); neither matches JS exactly
s.toUpperCase()s.to_uppercase()
s.split(",")s.split(',')
s.includes("x")s.contains("x")
s.trim()s.trim()
s.replace(a, b)s.replace(a, b)
s.startsWith("/")s.starts_with('/')
accept a string argumenttake &str, return String

See: Strings, String Manipulation.


Rust has no classes and no inheritance. Data lives in a struct or enum; behaviour lives in impl blocks; shared behaviour is a trait (an interface you can implement for any type).

TypeScript / JavaScriptRust
interface User { id: number }struct User { id: i32 }
class C { method() {} }struct C; impl C { fn method(&self) {} }
type Shape = Circle | Squareenum Shape { Circle, Square }
discriminated union with dataenum variants carry data
implements Serializableimpl Serializable for T
extends Base (inheritance)composition plus traits (no inheritance)
this&self, &mut self, or self
new C(args)C::new(args) (a convention, not a keyword)
instanceofmatch on an enum or a trait object
generic class Box<T>struct Box<T> with trait bounds

See: Structs, Enums, impl Blocks, Traits, Trait Objects.


The keywords match, but Rust futures are lazy (they do nothing until .awaited) and there is no built-in event loop, so you pick a runtime such as Tokio.

TypeScript / JavaScriptRust
Promise<T>impl Future<Output = T>
async function f()async fn f()
await pp.await
Promise.all([a, b])tokio::join!(a, b) / futures::future::join_all
Promise.race([a, b])tokio::select!
built-in event loopa runtime via #[tokio::main]
setTimeout(fn, ms)tokio::time::sleep(Duration::from_millis(ms)).await
for await (const x of stream)while let Some(x) = stream.next().await

See: Promises vs Futures, async/await, select and join, Async vs Sync.


TypeScript / JavaScriptRust
import { x } from "./m"use crate::m::x;
export function f()pub fn f()
export defaultno default export; name the item
a file is a moduledeclare modules with mod
package.jsonCargo.toml
npm install serdecargo add serde
npm run buildcargo build --release
node index.jscargo run
npm testcargo test
tsc (type-check)cargo check
ESLint / Prettiercargo clippy / cargo fmt
node_modules/~/.cargo/ plus the target/ build dir

See: The Module Tree, The use Keyword, Visibility, Cargo.


TypeScript / JavaScriptRust
console.log(x)println!("{x}") or println!("{x:?}") for any Debug type
console.error(x)eprintln!("{x}")
quick debug printdbg!(x)
JSON.stringify(v)serde_json::to_string(&v)?
JSON.parse(s)serde_json::from_str(&s)?
Number("42")"42".parse::<i32>()?
x as Y (numeric)x as Y
typeof x (runtime)not needed; types are checked at compile time
object spread { ...a, b: 1 }struct update User { b: 1, ..a }
immutability by conventionimmutable by default; opt in with mut

See: Output, JSON with Serde, Serde Basics.


This page is the map; the territory is the rest of the guide. The one idea with no JavaScript analogue, and the one worth learning first, is ownership: who is responsible for each value and when it is freed. Start there.