Type Conversions
Compact uses the as keyword for type casts. The cast rules determine when conversions are allowed and whether they may fail at runtime.
Note: The official Midnight documentation uses bounded notation like
Uint<0..n>to describe types. In code examples, we use the shorthandUint<64>, which is equivalent toUint<0..2^64>— the upper bound of the bounded form is exclusive (verified with toolchain 0.31.1).
Cast Syntax
expression as Type
TypeScript-style casts like <Type>expression are not supported.
Cast Categories
The documentation defines three behaviors for allowed casts:
| Category | Description | Runtime Effect |
|---|---|---|
| Static | Changes only the static type | None |
| Conversion | Converts between representations | Always succeeds |
| Checked | Validates at runtime | May fail |
Allowed Casts Reference
The following table summarizes the allowed casts between types:
| From | To | Behavior |
|---|---|---|
Uint<0..m> | Uint<0..n> where m ≤ n | Static |
Uint<0..m> | Uint<0..n> where m > n | Checked (fails if value > n) |
Uint<0..m> | Field | Static |
Field | Uint<0..n> | Checked |
Field | Boolean | Conversion (0→false, others→true) |
Field | Bytes<n> | Conversion (runtime error if doesn’t fit) |
Bytes<m> | Field | Conversion (LSB first, checked if exceeds max Field) |
Bytes<m> | Bytes<n> where m == n | Static |
enum type | Field | Conversion |
enum type | Uint<0..n> | Conversion (variant index; verified 0.31.1) |
Uint<0..m> | Bytes<n> | Conversion (little-endian; verified 0.31.1) |
Bytes<m> | Uint<0..n> | Conversion (little-endian; verified 0.31.1) |
Uint<0..m> | enum type | Checked (fails at runtime past the last variant) |
Not allowed:
Bytes<m>→Bytes<n>wherem ≠ n
Upcasts (Always Safe)
Upcasts—casts from a type to a supertype—are always allowed and never result in a static or runtime error.
For Uint types, casting from a smaller range to a larger range is a static cast:
pragma language_version >= 0.16;
export circuit upcastExample(): Field {
const small: Uint<32> = 100;
// Uint<32> to Uint<64>: static cast (range fits)
const bigger: Uint<64> = small as Uint<64>;
// Uint to Field: static cast
const f: Field = bigger as Field;
return f;
}
Checked Casts (May Fail)
When casting from a larger range to a smaller range, the cast is checked at runtime:
pragma language_version >= 0.16;
export circuit checkedCastExample(): Uint<32> {
const big: Uint<64> = 50;
// Uint<64> to Uint<32>: checked cast
// Fails at runtime if value exceeds Uint<32> range
const smaller: Uint<32> = big as Uint<32>;
return smaller;
}
Field Conversions
The cast rules for Field:
Uint<0..m>→Field: static castField→Uint<0..n>: checked cast (may fail if value too large)Field→Boolean: conversion (0 becomes false, non-zero becomes true)
pragma language_version >= 0.16;
export circuit fieldToUint(): Uint<64> {
const f: Field = 42;
// Field to Uint: checked cast
const num: Uint<64> = f as Uint<64>;
return num;
}
Bytes and Field
The cast rules for Bytes:
Bytes<m>→Field: conversion (LSB first, checked if exceeds max Field)Field→Bytes<n>: conversion (runtime error if doesn’t fit)Bytes<m>→Bytes<n>: static only ifm == n
pragma language_version >= 0.16;
export circuit bytesToField(): Field {
// Create Bytes using Bytes[...] syntax
const b: Bytes<4> = Bytes[1, 2, 3, 4];
// Bytes to Field: conversion (LSB first)
const f: Field = b as Field;
return f;
}
Enum to Field
Enums can be cast to Field — and also directly to Uint<n> (both conversions yield the variant index):
pragma language_version >= 0.16;
export enum Status { pending, active, completed }
export circuit enumToField(): Field {
const s: Status = Status.active;
// Enum to Field: conversion
const f: Field = s as Field;
return f;
}
Note:
enum → Uint<n>is also a valid conversion, and integer → enum works as a checked cast that fails at runtime past the last variant index (verified with toolchain 0.31.1).
Key Points
- Use
asfor all casts — TypeScript-style<T>is not supported - Upcasts are always safe — Casting to a supertype never fails
Uint<0..m>→Uint<0..n>— Static ifm ≤ n, checked otherwiseUint→Field— Static castField→Uint— Checked cast (may fail)enum→Uint— Conversion (variant index); integer → enum is checked- Field conversions - Uint to Field is safe; Field to Uint is checked