Skip to content

Value Types

WebAssembly is a typed stack machine. Every value on the stack has a concrete type, and every function declares exactly what types it consumes and produces. But unlike most languages, Wasm has a very small set of types to choose from.

WebAssembly has exactly four value types:

TypeWidthKind
i3232-bitInteger
i6464-bitInteger
f3232-bitFloat
f6464-bitFloat

There are no strings, booleans, arrays, or objects at the Wasm level. Everything is a number. Boolean logic is represented with i32 values where 0 means false and any non-zero value means true.

Each type has a const instruction that pushes a literal value:

(module
(func (export "answer") (result i32)
i32.const 42))

For a 64-bit float:

(module
(func (export "pi") (result f64)
f64.const 3.14159265358979))

And for a 64-bit integer — note that i64 is special when crossing into JavaScript:

(module
(func (export "bignum") (result i64)
i64.const 1000000000000))

JavaScript’s number type is a 64-bit float, which can only represent integers exactly up to 2^53. An i64 can hold values far beyond that. To preserve the full precision, the WebAssembly JavaScript API converts i64 return values to BigInt rather than number. This means typeof result === 'bigint' — not 'number'.

You can verify this in the runner below.

WebAssembly
OptionBenefitCost
Writing WAT by handYou see clearly that every value on the stack has a fixed type (i32, i64, f32, f64), giving a detailed feel for Wasm’s type systemYou must always pick the matching const/instruction yourself; get the type wrong and validation fails immediately
Letting a compiler generate Wasm (Rust/AssemblyScript)The compiler maps types from the source language to i32/i64/f32/f64 automatically, reducing type mistakesYou have to trust the compiler’s conversions, like i64 becoming a BigInt, without seeing exactly what happens in between
  • Pushing a value with the wrong-typed instruction — e.g. using i32.const when the function declares (result i64) — so what’s left on the stack at the end doesn’t match the signature and validation fails
  • Pushing constants in the wrong order before a computation instruction, producing a wrong result even though every pushed value has the correct type
  • Forgetting that JavaScript must receive an i64 as a BigInt, not a number, and then comparing or computing with it mixed directly with a regular number, causing a runtime TypeError

💡 Real-world example

The official WebAssembly spec testsuite — mirrored for convenience by tools like WABT — contains many hand-written .wat files covering every value type (i32, i64, f32, f64) to verify encoders/decoders interpret each one exactly per spec, including the case where i64 must convert to BigInt on the JavaScript side.

How many core value types does WebAssembly have?
What JavaScript type does a Wasm `i64` return value become?
Which instruction pushes a floating-point constant onto the stack?