IMPORTANT: To view this page as Markdown, append `.md` to the URL (e.g. /docs/manual/basics.md). For the complete Mojo documentation index, see llms.txt.
Skip to main content
Version: 1.0.0b2
For the complete Mojo documentation index, see llms.txt. Markdown versions of all pages are available by appending .md to any URL (e.g. /docs/manual/basics.md).

Mojo types reference

Mojo is statically typed. Every value has a type that is known at compile time. This page catalogs built-in types that are available in every program without an import.

Built-in types and the prelude

Built-in types come from the standard library prelude, which the compiler imports into every program. The prelude consists of the builtin package (Int, Bool, Error, and core traits) plus selected types from collections, memory, and math.

Although they feel like part of the language itself, built-in types are ordinary structs defined in the standard library, just like a type you might write yourself.

The prelude and compiler syntax are separate concerns. Some language constructs have syntax without a corresponding name in scope. For example, a set display doesn't require an import but the Set type does:

var primes = {2, 3, 5, 7} # set display: compiler syntax, no import

from std.collections import Set
var empty = Set[Int]() # the name Set must be imported

Numeric types

Mojo's numeric types are built on SIMD, a fixed-size, homogeneous vector of primitive values. Int, UInt, the sized integer types (Int8 through Int256 and UInt8 through UInt256), and the floating-point types (Float16 through Float64, BFloat16, and the Float8_* formats) are all available through the prelude.

For details on sizes, precision, overflow behavior, and conversions, see Numeric types.

String types

All string types hold UTF-8 encoded text. Their bytes are guaranteed to be valid UTF-8. Construction enforces this. String(from_utf8_lossy=...) replaces invalid bytes, and String(unsafe_from_utf8=...) requires the caller to guarantee validity.

TypeWhat it is
StringOwned, mutable, heap-allocated UTF-8 string.
StringSliceNon-owning view into existing UTF-8 data.
StaticStringA StringSlice over static, read-only data.
StringLiteralCompile-time string constant from source.
CodepointA single Unicode codepoint.

A string literal in source is a StringLiteral. It materializes to a String at runtime, or to a StringSlice when the context requires a view. For details, see String literals.

Length has three measurements, and they disagree for non-ASCII text:

var wave = String("👋🏽") # waving hand + skin-tone modifier
print(wave.byte_length()) # 8
print(wave.count_codepoints()) # 2
print(wave.count_graphemes()) # 1

byte_length() counts UTF-8 bytes, count_codepoints() counts Unicode codepoints, and count_graphemes() counts user-perceived characters. Pick the count that matches the question being asked.

Collection types

Mojo includes a flexible set of collection types.

TypeWhat it is
ListDynamically sized, growable sequence.
DictKey-value mapping.
SetUnordered collection of unique values. Requires an import.
OptionalA value that may or may not be present.
TupleFixed-size, heterogeneous group of values.
InlineArrayFixed-size array stored inline, with no heap allocation.
VariantHolds one value from a fixed set of types. Requires import.

List, Dict, Set, and Tuple support display syntax, as described in Expressions.

Set and Variant aren't in the prelude. Import Set from std.collections and Variant from std.utils.

Optional

An Optional[T] holds a T or nothing. It's truthy when a value is present:

var maybe: Optional[Int] = 5
if maybe:
print(maybe.value()) # 5

value() aborts on empty Optionals. Guard it with a truthiness check, or call or_else() to supply a default:

var empty: Optional[Int] = None
# empty.value() # aborts: the Optional is empty
print(empty.or_else(0)) # 0

Variant

A Variant holds one value from a fixed set of types, tracked at runtime. Test the active type with isa[T](), and read it by indexing with that type:

from std.utils import Variant

var v = Variant[Int, String](5)
print(v[Int]) # 5
v.set[String]("text")
print(v[String]) # text

Memory types

Mojo memory types are pointers and views that provide non-owning access to memory. They come in safe and unsafe forms, distinguished by the guarantees the compiler enforces. A Pointer is non-nullable and refers to initialized memory. UnsafePointer drops those guarantees, can refer to uninitialized memory, and leaves allocation and deallocation to you.

TypeWhat it is
PointerNon-nullable safe pointer to a single value.
UnsafePointerRaw pointer. No nullability or safety guarantees. Manual memory management.
SpanNon-owning view of contiguous data.
AddressSpaceIdentifies where memory lives, such as CPU or GPU.

OpaquePointer, OptionalUnsafePointer, and the Mut and Immut forms are aliases of UnsafePointer.

For allocation, pointer arithmetic, and lifetimes, see Pointers.

Other built-in types

Mojo includes several built-in types that don't fit into the above categories but are still fundamental to the language:

TypeWhat it is
BoolBoolean value, True or False. Backed by a 1-bit type.
ErrorA runtime error raised by a raises function.
NeverThe type of an expression that never produces a value.
NoneTypeThe type whose only value is None.
SliceThe start:end:step descriptor a subscript produces.

Bool

A Bool struct is backed by a 1-bit value, not a SIMD alias. Its literals are True and False. Any type that conforms to Boolable provides a Bool representation that can act as a condition:

var flag = True
if flag:
print("yes") # yes

Error

Error is Mojo's default error type. A function marked raises raises Error unless it declares another type (raises T):

def parse(s: String) raises -> Int:
raise Error("invalid input")

Never

Never is the type of an expression that never produces a value, such as a call that always aborts or a loop that never terminates. Values of type Never can't exist. The compiler treats any code that follows as unreachable. Never is a compiler type (!kgen.never), not a struct.

from std.os import abort

def fatal() -> Never:
abort() # never returns

None

None is the only value of type NoneType. A function with no declared return type returns None:

def implicit_greet(name: String):
print("hello", name)
# returns None implicitly

def explicit_greet(name: String) -> None:
print("hello", name)
# returns None explicitly

Slice

A Slice holds start, end, and step, each an Optional[Int]. It's the descriptor that subscript syntax with colons produces; it carries no data of its own.

What subscripting returns depends on the type being indexed. A contiguous List slice yields a Span view; a strided slice yields a new List.

var items = [0, 1, 2, 3, 4, 5]
var middle = items[1:4] # Span view, [1, 2, 3]
var strided = items[::2] # new List, [0, 2, 4]

For slice syntax, see Expressions.