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

Structs

Define structured data types with RStruct and field().

Defining a Struct

Use RStruct to define a schema with named fields:

// Demonstrates: Defining struct schemas with RStruct and field()

import { RStruct, RString, RU32, RBool, field } from "@grounds/schema";
import type { Static } from "@sinclair/typebox";

// Define a User schema
// Each field has a numeric ID (for wire format) and a type
const UserSchema = RStruct({
  id: field(0, RU32()),
  name: field(1, RString()),
  active: field(2, RBool()),
});

// Static<typeof Schema> extracts the TypeScript type
type User = Static<typeof UserSchema>;

// TypeScript now knows the exact shape
const user: User = {
  id: 12345,
  name: "Alice",
  active: true,
};

console.log("User schema defined successfully");
console.log("User object:", user);
console.log("TypeScript infers: { id: number, name: string, active: boolean }");

Field IDs

Each field has a numeric ID used in the wire format. Field IDs:

  • Must be unique within a struct
  • Are used for encoding (not the field name)
  • Allow schema evolution (add new IDs, deprecate old ones)

Type Inference

Use Static<typeof Schema> to extract the TypeScript type:

import type { Static } from "@sinclair/typebox";

type User = Static<typeof UserSchema>;
// { id: number; name: string; active: boolean }

Available Field Types

Schema TypeTypeScript TypeRelish Type
RString()stringString
RBool()booleanBool
RU8() - RU128()number / bigintu8 - u128
RI8() - RI128()number / biginti8 - i128
RF32(), RF64()numberf32, f64
RTimestamp()DateTimeTimestamp
ROptional(T)T | nullOptional wrapper
RArray(T)Array<T>Array

Next Steps

Learn about Enums for tagged unions, or Codecs for serialization.