Blogs/Technology

5 Rust Features I Wish JavaScript and Ruby Had

Written by Devesh Mhatre
Mar 13, 2026
11 Min Read
5 Rust Features I Wish JavaScript and Ruby Had Hero

While experimenting with a small Raspberry Pi setup for running lightweight applications, I started comparing how different programming languages behave under tight hardware constraints. I wrote this article to examine a few Rust features that stand out when viewed from the perspective of a JavaScript or Ruby developer.

As a full-stack developer, my first instinct was to build the tool using familiar stacks like Ruby on Rails or SvelteKit. But the hardware limitations made me reconsider whether those ecosystems were the most efficient choice.

Exploring Rust from that perspective revealed several built-in language features that solve problems JavaScript and Ruby developers often handle through conventions, libraries, or workarounds.

This article highlights five Rust features that feel particularly powerful when compared with JavaScript and Ruby, especially when thinking about reliability, safety, and tooling. I have been tinkering with low-level programming languages like C for almost half a decade now; even today, if you go to my personal GitHub account, the oldest repo you’ll find is a small learning app I had built with C. So, my curiosity about what is widely (and controversially) considered a successor to C was natural.

I have been learning Rust for less than three months now, and some of the in-built APIs have been blowing my mind since I came across them. So, I wanted to document these Rust features into a single article and view them from the perspective of a JavaScript/Ruby developer.

Fair warning, while I will be talking about Rust throughout the article here, this is not me advocating to my fellow JavaScript/Ruby developers to give Rust a try. There are quite a few prerequisites that you need to check before dipping your toes into a low-level language like Rust, lest you won’t have fun learning it.

Another fair warning, I am, by no means, an expert in Rust, as I have been a Rustacean for just a little over three months at this point. So, if I have misinterpreted something, please be kind to me.

I’m done with my preface! Let’s move on to 5 Rust features I wish JavaScript and Ruby had!

cargo doc --open

I know! A command as part of a section heading? What a weird way to start, right? But that was the first thing that blew my mind when I was learning about Cargo, Rust's default build system/package manager.

Cargo is the default build system and package manager for Rust projects. It handles compilation, dependency management, and publishing libraries to Rust’s package registry, crates.io, which plays a role similar to npm in the JavaScript ecosystem.

One command in Cargo is particularly impressive from a developer experience standpoint: cargo doc --open.

Instead of relying on external websites or scattered documentation sources, this command generates documentation for the entire project and its dependencies locally and opens it directly in the browser.

For developers working on large projects or older dependencies, this ability to access documentation locally can significantly improve productivity and reliability.

When you run this command, Cargo bundles all the documentation from your local package and all its dependencies. This documentation is stored locally in your project’s target/doc directory. The --open flag opens this documentation in your default browser once it is successfully built.

You might wonder what is so special about documentation. For that, let me tell you a dilemma I faced a couple of days ago while working on a React project that started in 2022. The project depended on the @reach/router package for handling in-app navigation. Unfortunately, Reach Router and React Router merged, and React Router remained the surviving package.

Some would consider this a natural progression of how two similar tech projects evolve. I would be one of those people if I wasn’t working on an older version of Reach Router and trying to find a way to open an internal <Link> in a new tab. Because React Router was the surviving project, I had to dig into forum posts and deprecated Reach Router documentation, only to discover it was impossible to do what I was trying to do.

Trust me, the frustration of searching through documentation and Stack Overflow answers only to hit a dead end kills the vibe!

As for the output of cargo doc --open, all the documentation is bundled from the respective crates, so no internet connection is needed. Even if my package relied on a crate that's been archived for a long time, I'd still be able to access its official documentation locally without opening a browser tab. I mean, Cargo would open it for me.

To get the same results but for Rust’s standard library, you’ll need to run the command rustup doc, and you are all set!

Any seasoned JavaScript developer worth their salt would tell you how grateful they would be if this method of documentation got introduced in the JavaScript ecosystem. For those of you who will come at me with pitchforks and arguments like JSDoc/TypeDoc already does the same thing, you, the developer, still need to manually link external library documentation. Standard library documentation is accessed online via MDN. So, not the same!

The same goes for Ruby! While you have RDoc and YARD to generate documentation for your project, the documentation (at least of the gems) has to be generated manually. At least Ruby standard library documentation is available locally via the command: ri --server. However, this command doesn’t automatically open the local documentation on the browser; you must navigate to the relevant port. So, not the same!

All Variables are Immutable by Default

Infographic titled “All Variables Are Immutable by Default in Rust.” It explains that Rust variables cannot be reassigned by default, require the “mut” keyword for mutation, encourage safer and predictable code, and improve code readability.

In Rust, variables are immutable by default. If a developer attempts to reassign a value to a variable without explicitly marking it as mutable, the compiler raises an error.

This design encourages predictable and safer code. Immutable data structures reduce accidental state changes and make concurrent programming significantly easier to reason about.

Let’s Develop Your JavaScript Project Together!

We build fast, reliable, and scalable JavaScript applications that power modern businesses across the web.

Rust requires developers to explicitly opt into mutability using the mut keyword. That small requirement forces deliberate decision-making about when and why data should change.

From a readability standpoint, immutability also makes code easier to understand because the potential behavior of variables becomes clearer at a glance. If you try to reassign a different value to that variable, the compiler will throw an error that will sound like this: cannot assign twice to immutable variable

But why is this a feature? Shouldn’t this be counted as a handicap? Well, that depends on what is important to you. If you want to write concurrency-safe and predictable code, you will appreciate immutable variables. If you know anything about bugs caused by data races and accidental data modification, you’ll understand why such a feature would be a godsend.

Plus, Rust requiring developers to explicitly add the mut keyword to any variable that they want to turn mutable makes sure that the developers think long and hard about when and why data should be modified in their programs.

Even from a readability perspective, this is quite useful, as you can tell simply by looking at a variable’s definition if the variable is going to throw any curveballs at you down the line somewhere.

Having said that, and keeping the article’s raison d'être in mind, would it be a good idea to introduce immutability in dynamic languages like JavaScript and Ruby? Well, no. See, even if both JavaScript and Ruby had immutability built into them from their inception, there would still be challenges, such as the learning curve for developers! Imagine you are a newbie JavaScript developer who’s trying to learn new concepts about the language. Now imagine being restricted by immutability from modifying any variable as or when you see fit.

See, mutability by default is so ingrained in most popular programming languages that even the thought of immutability always being a part of such languages from the very beginning makes us wonder how difficult it would have been to pick up these languages as easily as you did.

While I'd love to see immutability by default in JavaScript and Ruby for the many benefits and optimizations it could offer, if I take off my rose-tinted glasses and face reality, I’d prefer the mutability and accessibility of these languages over immutability with the added complexities it brings.

Variable Shadowing

Rust allows developers to declare a new variable with the same name as a previously defined variable. This behavior is known as variable shadowing.

Instead of mutating the original variable, Rust creates a new variable with the same name that replaces the earlier one within the current scope.

This approach allows developers to transform data step-by-step without introducing additional variable names. It keeps the code concise while maintaining type safety.

Although JavaScript and Ruby technically allow shadowing through scopes, the behavior is often less predictable. Rust’s explicit variable model makes shadowing easier to reason about and safer to use. Sounds weird, right? Let me demonstrate it with a small code snippet:

// Create a new variable with the name given_string
let given_string = String::from("Hello, world!");


// Usually, in JS or Ruby, you would create another variable
// with a different name like given_string_len in this case
// 
// But in Rust, due to variable shadowing, you can safely use the same variable
// name and even assign it a value with a different type
let given_string = given_string.len();

println!("{given_string}"); // 13

Here, the second given_string definition shadows the first one. As a result, the second given_string variable is used, and the first given_string variable becomes inaccessible. Usually, you would use this feature in cases where you want to reuse the same variable name and assign it a new value, probably of a different type.

Now, granted that both JavaScript and Ruby allow variable shadowing. But due to the presence of scopes in both of these languages, you end up writing code that looks a little something like this:

let string = "Hello, World!";
let stringLen = string.length;

console.log(stringLen); // 13

Even though it is completely possible to use the same variable name in line 2, without the let keyword, to get the same result, most of us end up creating a new variable with a new name due to the chaotic nature of variable shadowing in both JavaScript and Ruby.

I wish there was a way to make block-based behavior between variables more predictable in JavaScript and Ruby. That would certainly make variable shadowing more reliable.

No Null

Rust avoids traditional null values entirely. Instead, it uses the Option type to represent values that may or may not exist.

An Option<T> can either contain Some(value) or None. This forces developers to explicitly handle both possibilities during compilation.

By requiring explicit handling of missing values, Rust eliminates many runtime errors caused by null pointer dereferencing.

Languages like JavaScript and Ruby allow null values to propagate through code until they fail at runtime. Rust’s approach moves that responsibility to compile time, which improves reliability in production systems. In JavaScript and Ruby, variables can either be null or not null. Rust doesn’t have that, however. Instead, Rust uses the Option type to represent that there may or may not be a value present. Through the Option type, Rustaceans avoid the usual pitfalls related to null pointers, such as null pointer dereferencing, leading to runtime errors.

// A function that accepts an option parameter of type Option<i32>
// i32 = Signed 32-bit integer
fn get_value(option: Option<i32>) {
    // We use a match expression to compare the value option represents
    // with all possible patterns
    //
    // As you can see, even when there isn’t a value present, we can
    // gracefully handle the case
    match option {
        Some(v) => println!("The value is: {}", v),
        None => println!("No value."),
    }
}

As you can see from the above code snippet, using Option<T>, Rust forces developers to explicitly handle the possibility of null, which helps them make their code avoid any runtime errors in production.

Unfortunately, neither JavaScript nor Ruby enforce null safety in the same way as Rust. However, workarounds can be employed to get the same functionality as the Option type.

In JavaScript, you can either simulate Option using a library like fp-ts or create your own custom implementation of the Option type. In Ruby, unfortunately, there is only the custom implementation way of mimicking the Option type.

In practice, this matters when consuming third-party commerce APIs, fields may be absent or partially populated (e.g., payloads from Shopify dropshipping apps. Modeling such data as Option<T> helps keep parsers explicit and avoids runtime surprises.

Hopefully, both these languages receive a built-in solution, like the Option type, to handle null safety without any hacky workarounds.

No Need to Install Rust Runtime on Your Server

Let’s revisit my use case of wanting to serve a small internal tool from my 512MB RPi board. When I tried installing Rust on that board, it completely crashed, even though I used a non-GUI setup. The reason? Unfortunately, Rust installation requires more than half a gig of space.

Rust applications compile into standalone binaries. Once compiled, the application can run on a target machine without requiring the Rust runtime to be installed.

This behavior makes Rust applications highly portable, especially for constrained environments or embedded systems.

Let’s Develop Your JavaScript Project Together!

We build fast, reliable, and scalable JavaScript applications that power modern businesses across the web.

In contrast, languages such as JavaScript and Ruby depend on runtime environments like Node.js or the Ruby interpreter. Without those runtimes installed, the application cannot execute.

Because Rust produces compiled binaries, deployment becomes simpler in environments where installing large runtime ecosystems may not be practical. The same goes for Ruby!

But the thing about Rust is that, even if Rust is not installed on my board, it can still serve my app as long as I compile it on my workstation and then execute the binary on my board. This makes my Rust app way more portable compared to JavaScript/Ruby or any interpreted language for that matter. Plus, since I didn’t need to install Rust on my board, it led to the efficient performance of my app.

This feature, similar to the immutability feature, falls under the architecturally impossible category. Since neither JavaScript nor Ruby is a compiled language, there is no way to emulate this behavior in either of these languages. So, while I wish something like this could be possible to bring into the JavaScript/Ruby ecosystem, all I can do is bite the bullet and do things how they are supposed to be done here.

Rant: Is it just me, or do other Ruby developers also face issues getting their Ruby environment up and running, even after Dockerizing the project?

Frequently Asked Questions

What makes Rust different from JavaScript and Ruby?

Rust focuses heavily on memory safety, compile-time error detection, and predictable performance. JavaScript and Ruby prioritize developer flexibility and rapid development.

Why are Rust variables immutable by default?

Rust uses immutability to prevent accidental data modification and improve code safety. Developers must explicitly mark variables as mutable if they intend to modify them.

What problem does Rust’s Option type solve?

The Option type eliminates null pointer errors by forcing developers to explicitly handle missing values during compilation.

What is Cargo in Rust?

Cargo is Rust’s official build system and package manager. It handles compilation, dependency management, documentation generation, and library publishing.

Why can Rust run without a runtime environment?

Rust compiles programs into standalone binaries. Unlike interpreted languages, these binaries can run directly on a system without requiring a separate runtime installation.

Is Rust a replacement for JavaScript or Ruby?

Rust is designed for different use cases. While JavaScript and Ruby are optimized for rapid development and web ecosystems, Rust excels in performance-critical systems and infrastructure software.

Conclusion

Rust is a language with a steep learning curve, but many of its design decisions are aimed at improving reliability, developer tooling, and runtime safety.

Looking at Rust through the perspective of a JavaScript or Ruby developer highlights how differently programming languages can approach the same problems.

Features such as immutability by default, explicit null handling, and built-in tooling illustrate how language design choices influence developer experience and system reliability.

Whether developers choose to adopt Rust or continue using higher-level languages, examining these design patterns provides useful insight into how modern programming languages evolve. Based on what I've experienced so far, I'm starting to like the language and naturally find myself comparing it to JavaScript and Ruby, as those are the two languages I feel most confident with.

Writing this article gave me a lot of clarity, not only about Rust but also about JavaScript and Ruby, which was my goal from the beginning. Whether you fully agree with everything I've written in this article or not, I hope it has provided you with some clarity about these three languages, no matter your level of confidence in them.

Author-Devesh Mhatre
Devesh Mhatre

Tech enthusiast with a passion for open-source software and problem-solving. Experienced in web development, with a focus on React, React Native and Rails. I use arch (and neovim) btw ;)

Share this article

Phone

Next for you

8 Best GraphQL Libraries for Node.js in 2025 Cover

Technology

Jan 29, 20268 min read

8 Best GraphQL Libraries for Node.js in 2025

Why do some GraphQL APIs respond in milliseconds while others take seconds? The difference often comes down to choosing the right GraphQL library for Node.js. According to npm trends, Apollo Server Express alone sees over 800,000 weekly downloads, proving that developers need reliable tools to build production-ready GraphQL servers. The truth is, building GraphQL APIs in Node.js has never been easier, but picking the wrong library can slow down your entire application. Modern web applications d

I Tested 9 React Native Animation Libraries (Here’s What Works) Cover

Technology

Feb 10, 202614 min read

I Tested 9 React Native Animation Libraries (Here’s What Works)

Why do some mobile apps feel smooth while others feel clunky? I’ve noticed the difference is usually animations under load, especially during scrolling, navigation, and gesture-heavy screens. Google research shows 53% of mobile site visits are abandoned if pages take longer than three seconds to load, and the same performance expectations carry over to mobile apps. The truth is, smooth animations in React Native apps are no longer a luxury; they’re a must-have for a modern, engaging user experi

9 Critical Practices for Secure Web Application Development Cover

Technology

Jan 29, 20267 min read

9 Critical Practices for Secure Web Application Development

In 2026, developing modern web applications requires a balance between speed and security. Product strategy often pressures development teams to move fast, and ignoring application security can cause catastrophic results. For example, post-credential-based attacks have caused over $5 billion in losses. Security vulnerabilities in web applications are not just technical security problems; they are a business risk. The truth is that security incidents happen when web developers think about web se