Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Type System

TeaLeaf has a rich type system covering primitives, containers, and type modifiers.

Primitive Types

TypeAliasesDescriptionBinary Size
booltrue/false1 byte
int8Signed 8-bit integer1 byte
int16Signed 16-bit integer2 bytes
intint32Signed 32-bit integer4 bytes
int64Signed 64-bit integer8 bytes
uint8Unsigned 8-bit integer1 byte
uint16Unsigned 16-bit integer2 bytes
uintuint32Unsigned 32-bit integer4 bytes
uint64Unsigned 64-bit integer8 bytes
float3232-bit IEEE 754 float4 bytes
floatfloat6464-bit IEEE 754 float8 bytes
stringUTF-8 textvariable
bytesRaw binary datavariable
json_numberArbitrary-precision numeric string (from JSON)variable
timestampUnix milliseconds (i64) + timezone offset (i16)10 bytes

Type Modifiers

field: string          # required string
field: string?         # nullable string (can be ~)
field: []string        # required array of strings
field: []string?       # nullable array of strings (the field itself can be ~)
field: []user          # array of structs

The ? modifier applies to the field, not array elements. However, the parser does accept ~ (null) values inside arrays, including schema-typed arrays. Null elements are tracked in the null bitmap.

Value Types (Not Schema Types)

The following are value types that appear in data but cannot be declared as field types in @struct:

TypeDescription
objectUntyped { key: value } collections
mapOrdered @map { key: value } with any key type
refReference (!name) to another value
taggedTagged value (:tag value)

For structured fields, define a named struct and use it as the field type. For tagged values with a known set of variants, define a @union – this provides schema metadata (variant names, field names, field types) that is preserved in the binary format.

Type Widening

When reading binary data, automatic safe conversions apply:

  • int8int16int32int64
  • uint8uint16uint32uint64
  • float32float64

Narrowing conversions are not automatic and require recompilation.

Type Inference

Standalone Values

When writing, the smallest representation is selected:

  • Integers: i8 if fits, else i16, else i32, else i64
  • Unsigned: u8 if fits, else u16, else u32, else u64
  • Floats: always f64 at runtime

Homogeneous Arrays

Arrays of uniform type use optimized encoding:

Array ContentsEncoding Strategy
Schema-typed objects (matching a @struct)Struct array encoding with null bitmaps
Value::Int arraysPacked Int32 encoding
Value::String arraysString table indices (u32)
All other arrays (UInt, Float, Bool, mixed, etc.)Heterogeneous encoding with per-element type tags

Type Coercion at Compile Time

When compiling schema-bound data, type mismatches use default values rather than erroring:

Target TypeMismatch Behavior
Numeric fieldsIntegers/floats coerce; non-numeric becomes 0
String fieldsNon-string becomes empty string ""
Bytes fieldsNon-bytes becomes empty bytes (length 0)
Timestamp fieldsNon-timestamp becomes epoch (0)

This “best effort” approach prioritizes successful compilation over strict validation. Validate at the application level before compilation for strict type checking.

Bytes Literal

The text format supports b"..." hex literals for byte data:

payload: b"cafef00d"
empty: b""
checksum: b"CA FE"   # ERROR -- no spaces allowed
  • Contents are hex digits only (uppercase or lowercase)
  • Length must be even (2 hex chars per byte)
  • dumps() and decompile emit b"..." for Value::Bytes, enabling full text round-trip
  • JSON export encodes bytes as "0xcafef00d" strings; JSON import does not auto-convert back to bytes