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

Enums

Define tagged unions with REnum and variant().

Defining an Enum

Use REnum to define a schema with named variants:

// Demonstrates: Defining enum schemas with REnum and variant()

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

// Define struct schemas for each variant
const TextMessageSchema = RStruct({
  content: field(0, RString()),
  sender: field(1, RString()),
});

const ImageMessageSchema = RStruct({
  url: field(0, RString()),
  width: field(1, RU32()),
  height: field(2, RU32()),
});

// Define an enum with named variants
// Each variant has a numeric ID (for wire format) and a schema
const _MessageSchema = REnum({
  text: variant(0, TextMessageSchema),
  image: variant(1, ImageMessageSchema),
});

// Extract types for each variant
type TextMessage = Static<typeof TextMessageSchema>;
type ImageMessage = Static<typeof ImageMessageSchema>;

// Create instances of each variant
const textMsg: TextMessage = { content: "Hello!", sender: "Alice" };
const imageMsg: ImageMessage = { url: "https://example.com/img.png", width: 800, height: 600 };

console.log("Enum schema defined successfully");
console.log("Text message:", textMsg);
console.log("Image message:", imageMsg);

Variant IDs

Each variant has a numeric ID used in the wire format:

  • Must be unique within an enum
  • Determines which variant is encoded
  • Allows schema evolution (add new variants)

Variant Types

Variants can contain any schema type:

const ResultSchema = REnum({
  success: variant(
    0,
    RStruct({
      data: field(0, RString()),
    }),
  ),
  error: variant(
    1,
    RStruct({
      code: field(0, RU32()),
      message: field(1, RString()),
    }),
  ),
});

Discrimination

After decoding, use type guards or discriminator fields to narrow the type:

function isTextMessage(msg: unknown): msg is TextMessage {
  return typeof msg === "object" && msg !== null && "content" in msg;
}

Next Steps

Learn about Codecs for encoding and decoding.