Data Types
Esta página aún no está disponible en tu idioma.
Rust’s type system is one of the major differences from JavaScript. Let’s explore the various data types in Rust and how they compare to JavaScript.
Type Systems: Static vs Dynamic
JavaScript is dynamically typed, meaning variables can change types at runtime:
let value = 42; // Numbervalue = "hello"; // Now it's a Stringvalue = true; // Now it's a Boolean
Rust is statically typed, meaning every variable’s type must be known at compile time:
let value = 42; // i32 by default// value = "hello"; // ❌ Error: mismatched types// value = true; // ❌ Error: mismatched types
In Rust, you can explicitly annotate types:
let age: u32 = 30;let name: String = String::from("Alice");let is_active: bool = true;
Scalar Types
Integers
JavaScript has a single numeric type (Number
) for integers and floating-point values, plus BigInt
for large integers.
Rust has multiple integer types based on size and signedness:
Type | Size (bits) | Range | JS Equivalent |
---|---|---|---|
i8 | 8 | -128 to 127 | Number |
u8 | 8 | 0 to 255 | Number |
i16 | 16 | -32,768 to 32,767 | Number |
u16 | 16 | 0 to 65,535 | Number |
i32 | 32 | -2,147,483,648 to 2,147,483,647 | Number |
u32 | 32 | 0 to 4,294,967,295 | Number |
i64 | 64 | -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 | BigInt |
u64 | 64 | 0 to 18,446,744,073,709,551,615 | BigInt |
i128 | 128 | Very large range | BigInt |
u128 | 128 | Very large range | BigInt |
isize | arch | Depends on architecture | Number |
usize | arch | Depends on architecture | Number |
let a: i32 = 42; // 32-bit signed integerlet b: u64 = 1000000; // 64-bit unsigned integerlet c = 98_222; // Underscores for readability, like 98,222let d = 0xff; // Hex valuelet e = 0o77; // Octal valuelet f = 0b1111_0000; // Binary value
In JavaScript, all these would be:
const a = 42; // Numberconst b = 1000000; // Numberconst c = 98222; // Numberconst d = 0xff; // Hex value (255)const e = 0o77; // Octal value (63)const f = 0b11110000; // Binary value (240)const g = 9007199254740992n; // BigInt for numbers > 2^53
Floating-Point Numbers
Rust has two floating-point types:
Type | Size (bits) | Precision | JS Equivalent |
---|---|---|---|
f32 | 32 | Single precision | Number |
f64 | 64 | Double precision | Number |
let x: f64 = 2.0; // Double-precision float (default)let y: f32 = 3.0; // Single-precision float
In JavaScript:
const x = 2.0; // Number (always double precision)
Booleans
Both languages have boolean types:
let t: bool = true;let f: bool = false;
const t = true;const f = false;
Characters
JavaScript doesn’t have a dedicated character type; single characters are just strings of length 1.
Rust’s char
type represents a Unicode scalar value:
let c: char = 'z';let z: char = 'ℤ';let heart: char = '❤';
In JavaScript:
const c = 'z'; // String of length 1const z = 'ℤ'; // String of length 1 (but 2 bytes in UTF-16)const heart = '❤'; // String of length 1 (but 2 bytes in UTF-16)
Compound Types
Tuples
Rust has tuples, which are fixed-length collections of values of different types:
let tup: (i32, f64, u8) = (500, 6.4, 1);
// Destructuringlet (x, y, z) = tup;println!("y is: {}", y); // 6.4
// Accessing by indexlet five_hundred = tup.0; // 500
JavaScript added tuple-like behavior with array destructuring:
// JavaScript doesn't have real tuples, but we can use arraysconst tup = [500, 6.4, 1];
// Destructuringconst [x, y, z] = tup;console.log(y); // 6.4
// Accessing by indexconst fiveHundred = tup[0]; // 500
Arrays
Rust arrays have a fixed length and contain elements of the same type:
// Array with 5 elements of type i32let a: [i32; 5] = [1, 2, 3, 4, 5];
// Initialize an array with the same value repeatedlet b = [3; 5]; // Equivalent to [3, 3, 3, 3, 3]
// Access elementslet first = a[0]; // 1
JavaScript arrays are dynamic and can contain elements of different types:
// JavaScript arrays are dynamicconst a = [1, 2, 3, 4, 5];a.push(6); // Can add elements
// Can contain mixed typesconst mixed = [1, "two", true, { four: 4 }];
// Access elements the same wayconst first = a[0]; // 1
For dynamic arrays in Rust, you’d use a Vec
(vector), which we’ll cover in the Collections section.
Strings
Strings are a complex topic in Rust, especially coming from JavaScript.
JavaScript Strings
In JavaScript, strings are simple:
const greeting = "Hello, world!";const name = 'Alice';const template = `Hello, ${name}!`;
// String methodsconst upperName = name.toUpperCase();const sub = greeting.substring(0, 5); // "Hello"
Rust Strings
Rust has two string types: String
and &str
:
// String literals are &str (string slices)let greeting: &str = "Hello, world!";
// String type is growable, heap-allocatedlet mut name = String::from("Alice");name.push_str(" Smith"); // Now "Alice Smith"
// Creating a String from a &strlet s = "initial".to_string();let s = String::from("initial");
// Concatenationlet hello = String::from("Hello, ");let world = String::from("world!");let hello_world = hello + &world; // Note: hello is moved here
// Format macro (like template literals)let name = "Alice";let greeting = format!("Hello, {}!", name);
The main differences:
&str
is immutable and often used for string literals or views into stringsString
is growable, heap-allocated, and owned- Rust strings are UTF-8 encoded, which affects how they’re indexed and manipulated
Type Conversion
JavaScript Type Coercion
JavaScript often performs implicit type conversion:
console.log("5" + 1); // "51" (string)console.log("5" - 1); // 4 (number)console.log(5 + true); // 6 (number)
Rust Explicit Conversion
Rust requires explicit conversion:
let x = 5;// let y = x + "10"; // ❌ Error: cannot add `&str` to `{integer}`
// Explicit conversionlet y = x + 10; // 15let s = x.to_string() + "10"; // "510"let z = x + "10".parse::<i32>().unwrap(); // 15
Special Types
The Unit Type
Rust has a unit type ()
, which represents the absence of a value:
// Functions with no return value implicitly return the unit typefn do_something() { println!("Hello"); // Implicitly returns ()}
JavaScript doesn’t have an equivalent; functions that don’t return anything implicitly return undefined
.
The Option Type
Instead of null
or undefined
, Rust uses Option<T>
to represent a value that might be absent:
let some_number = Some(5);let some_string = Some("a string");let absent_number: Option<i32> = None;
// Using Option requires handling both casesmatch some_number { Some(n) => println!("Got a number: {}", n), None => println!("No number"),}
JavaScript equivalent:
const someNumber = 5;const someString = "a string";const absentNumber = null;
// Check for null/undefinedif (someNumber !== null && someNumber !== undefined) { console.log(`Got a number: ${someNumber}`);} else { console.log("No number");}
Type Inference
Both languages can infer types, but Rust’s inference is more sophisticated and happens at compile time:
// Rust infers these typeslet x = 5; // i32let y = 3.0; // f64let active = true; // bool
// JavaScript also has type inference, but at runtimelet x = 5; // numberlet y = 3.0; // numberlet active = true; // boolean
Type Aliases
Rust allows you to create type aliases:
type Kilometers = i32;
let distance: Kilometers = 5;
In JavaScript with TypeScript:
type Kilometers = number;
let distance: Kilometers = 5;
Next Steps
Now that you understand Rust’s data types, you’re ready to move on to Functions, where we’ll explore how to define and use functions in Rust compared to JavaScript.