Types

Mojo is statically typed. Every value has a type known at compile time. This is fundamentally different from Python, where types are checked at runtime. Static typing lets the compiler allocate exact memory sizes and generate specialized machine instructions.

Code

fn main():
    var age: Int = 30
    var temperature: Float64 = 98.6
    var is_active: Bool = True
    var name: String = "Mojo"

    print(age)
    print(temperature)
    print(is_active)
    print(name)

For formatted string in mojo, use: print(t"Hello, {name}!")

Primitive Types

  • Int — 64-bit signed integer (maps directly to a CPU register)
  • Int8, Int16, Int32 — fixed-width integers
  • UInt8, UInt64 — unsigned integers
  • Float16, Float32, Float64 — IEEE floating point
  • Bool — True or False
  • String — heap-allocated text

As always, try to use Int and Float64 by default. Only use the other types when necessary.

Compile-Time vs Runtime

Types are resolved at compile time. The compiler rejects type mismatches before your code runs:

fn main():
    let x: Int = 10
    # let y: Int = "hello"  # ERROR: cannot convert String to Int

Constraint

Declare variables of type Int8, Float32, and UInt64. Print their values. Try assigning a Float64 to an Int variable and observe the compiler error.

Why It Matters

An Int is exactly 8 bytes. A Float32 is exactly 4 bytes. The compiler uses this to pack data tightly, align memory for SIMD, and choose the right CPU instructions. Dynamic typing forces the runtime to carry type tags and check them on every operation — that overhead disappears with static types.