A comprehensive reference for all data types in Noir, including Field elements, integers, booleans, strings, arrays, vectors, tuples, structs, references, and function types.
Use this file to discover all available pages before exploring further.
Every value in Noir has a type, which determines which operations are valid for it. All values in Noir are fundamentally composed of Field elements. Abstractions are added on top to introduce different data types.Noir has two categories of data types: primitive types (e.g. Field, integers, bool) and compound types that group primitive types (e.g. arrays, tuples, structs).
All primitive types in Noir are private by default. Mark values as pub when they should be revealed to the verifier. This meaning of pub on a type (e.g. pub Field) is distinct from pub on a function (e.g. pub fn foo()).
The Field type corresponds to the native field type of the proving backend. Its size depends on the elliptic curve used — for example, 254 bits when paired with the default Grumpkin curve backend.Fields support standard integer arithmetic:
fn main(x: Field, y: Field) { let z = x + y;}
If proving efficiency is a priority, prefer Field as the default type. Smaller integer types like u64 incur extra range constraints.
The standard library also provides wrapping_sub and wrapping_mul.
When an integer literal appears without an explicit type, it defaults to Field unless another type is inferred. Loop indices default to u64. Use type suffixes like 1_u32 or 3i64 to be explicit.
Booleans are most commonly used in if expressions and assert statements.
Noir does not support the short-circuit logical operators || and &&. Use the bitwise operators | and & instead — they behave identically for booleans without the short-circuit evaluation, which is inefficient for ZK backends.
let my_val = 5;let mut flag = 1;if (my_val > 6) | (my_val == 0) { flag = 0;}
fn main() { let array = [42, 42]; assert(array.len() == 2); let arr = [42, 32]; let sorted = arr.sort(); assert(sorted == [32, 42]); let sorted_desc = arr.sort_via(|a, b| a >= b); assert(sorted_desc == [42, 32]);}
map, fold, reduce
let a = [1, 2, 3];let b = a.map(|x| x * 2); // [2, 4, 6]fn main() { let arr = [2, 2, 2, 2, 2]; let folded = arr.fold(0, |a, b| a + b); assert(folded == 10); let reduced = arr.reduce(|a, b| a + b); assert(reduced == 10);}
all, any, concat
fn main() { let arr = [2, 2, 2, 2, 2]; assert(arr.all(|a| a == 2)); let arr2 = [2, 2, 2, 2, 5]; assert(arr2.any(|a| a == 5)); let arr1 = [1, 2, 3, 4]; let arr3 = [6, 7, 8, 9, 10, 11]; let concatenated = arr1.concat(arr3); assert(concatenated == [1, 2, 3, 4, 6, 7, 8, 9, 10, 11]);}
Arrays in Noir are fixed size. Use dynamic indexing (non-constant indices) with care — it incurs a slight runtime cost. Mutable references to array elements are not supported.
// Public struct with mixed field visibilitypub struct Animal { hands: Field, // private to its module pub(crate) legs: Field, // accessible from the entire crate pub eyes: u8, // accessible from anywhere}