Types as arguments and nest freely, so a schema can
describe structured data without falling back to the dynamic encoder.
Optional
Type<T?>
Writes a one-byte presence flag, then the inner value only if it is not
nil.Type<T>
required
The inner type, used only when the value is present.
Size
A
nil costs one byte, which is the same as the dynamic encoder’s TYPE_NIL tag. The flag
is only overhead when the value is usually present, so do not wrap fields that are never
nil.Array
Type<{T}>
A varint element count followed by each element encoded with
t.Type<T>
required
The element type. Every element has to be encodable by it, because arrays are homogeneous.
number
Optional maximum element count, asserted on write.
Read preallocates with table.create(n), so decoding a large array does not repeatedly
resize.
Arrays are homogeneous and dense.
T.Array(T.UInt8()) over { 1, "two", 3 } errors on the
second element, and a sparse table like { [1] = "a", [3] = "c" } has #v == 1, so only the
first element is written and the rest is silently lost. Use T.Array(T.Any()) for mixed
contents, or a T.Struct() if the shape is actually fixed.Struct
Type<table>
Encodes named fields in declared order. No keys are transmitted, because the layout carries
them.
{ { string | Type } }
required
An array of
{ name, type } pairs. The order is part of the wire format.This is the most byte-efficient way to send a table. Compare the payload above:
String keys dominate dynamically encoded dictionaries, and a struct removes them entirely.
Only declared fields are transmitted. Extra keys on the table are ignored, and a missing key
is read as
nil and passed to the field’s Write, which errors for any non-optional type.
Wrap fields that may be absent in T.Optional.The type annotation is
{{ string } | Type}, which is loose, so Luau will not check that your
pairs are well formed. A typo like { T.UInt16(), "Health" }, with the order reversed, passes
analysis and fails at runtime with a nil index error. Write the name first.Nesting
Composites take anyType, including each other.
Choosing a composite
Next steps
Schemas guide
When schemas are worth declaring at all.
Custom types
Writing your own
Write and Read pair.