npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@uzon/uzon

v0.10.2

Published

UZON parser and evaluator for TypeScript/JavaScript

Downloads

94

Readme

uzon

TypeScript/JavaScript implementation of UZON — a typed configuration language.

npm install @uzon/uzon

Quick Start

import { parse } from "@uzon/uzon";

const config = parse(`
    host is "localhost"
    port is 8080
    debug is true
`);

console.log(config.host);  // "localhost"
console.log(config.port);  // 8080n (bigint)
console.log(config.debug); // true

UZON at a Glance

UZON is a configuration and data format with a rich type system:

// Primitives and typed numerics
name is "Alice"
age is 30
rate is 3.14 as f32
active is true
nothing is null

// Lists and tuples
tags are "api", "v2"
point is (10, 20)
matrix is [[ 1, 2 ], [ 3, 4 ]]

// Structs (nested objects)
database is {
    host is "localhost"
    port is 5432
}

// Enums and tagged unions
color is red from red, green, blue called Color
status is "ok" named success from success as string, failure as string

// Expressions and string interpolation
total is price * quantity
greeting is "Hello, {name}!"
label is first_name ++ " " ++ last_name

// Conditionals
tier is if score >= 90 then "gold" else "silver"
msg is case level
    when high then "critical"
    when low then "minor"
    else "normal"

// Type dispatch on unions
result is case type value
    when i32 then "integer"
    when string then "text"
    else "other"

// Variant dispatch on tagged unions
output is case named status
    when success then "ok"
    when failure then "error"
    else "unknown"

// Type checking
valid is x is type i32
wrong is x is not type string

// Functions
double is function n as i32 returns i32 { n * 2 }
evens is std.filter(numbers, function n as i64 returns bool { n % 2 is 0 })

// Struct override and extension
production is base with { debug is false }
point3d is point plus { z is 0 as i32 }

// Conversions and environment variables
port is env.PORT to u16 or else 8080

// Struct imports
shared is struct "./shared"

For the full language specification, see UZON Specification.

Value Types

UZON values in TypeScript are represented by the UzonValue type:

| UZON type | TypeScript type | Example | |--------------|-----------------------------|---------------------------------------------| | integer | bigint | 42n | | float | number | 3.14 | | string | string | "hello" | | bool | boolean | true | | null | null | null | | list | UzonValue[] | [1n, 2n, 3n] | | tuple | UzonTuple | UzonTuple([1n, "a"]) | | struct | Record<string, UzonValue> | { host: "localhost" } | | enum | UzonEnum | UzonEnum("red", ["red", "green", "blue"]) | | union | UzonUnion | UzonUnion(42n, ["i32", "string"]) | | tagged union | UzonTaggedUnion | UzonTaggedUnion(42n, "ok", variants) | | function | UzonFunction | (first-class, pure) | | undefined | typeof UZON_UNDEFINED | sentinel for unresolved lookups |


API Reference

Parsing

parse(source, options?)

Parse UZON source text and return evaluated bindings.

function parse(source: string, options?: ParseOptions): Record<string, UzonValue>;
function parse(source: string, options: ParseOptions & { native: true }): Record<string, any>;

By default, returns UzonValue types. Pass { native: true } to get plain JS types (numbers instead of bigints, etc.).

import { parse } from "@uzon/uzon";

// Default: UzonValue types
const r = parse('x is 42');
r.x; // 42n (bigint)

// Native: plain JS types
const r2 = parse('x is 42', { native: true });
r2.x; // 42 (number)

// With bigint mode
const r3 = parse('x is 42', { native: true, bigint: "string" });
r3.x; // "42"

parseFile(filePath, options?)

Parse a UZON file from disk. Struct imports are resolved relative to the file's directory.

function parseFile(filePath: string, options?: ParseOptions): Record<string, UzonValue>;
function parseFile(filePath: string, options: ParseOptions & { native: true }): Record<string, any>;
import { parseFile } from "@uzon/uzon";

const config = parseFile("config.uzon");
const native = parseFile("config.uzon", { native: true });

ParseOptions

interface ParseOptions {
  env?: Record<string, string>;           // Environment variables for env.* references
  filename?: string;                       // Filename for error messages
  fileReader?: (path: string) => string;   // Custom file reader (default: readFileSync)
  native?: boolean;                        // Convert to plain JS types
  bigint?: "number" | "bigint" | "string"; // bigint conversion mode (default: "number")
}

Stringify

stringify(bindings, options?)

Convert a record of bindings back to UZON source text.

function stringify(bindings: Record<string, any>, options?: StringifyOptions): string;
import { parse, stringify } from "@uzon/uzon";

const config = parse('host is "localhost"\nport is 8080');
stringify(config);
// 'host is "localhost"\nport is 8080'

stringifyValue(value, indent?, multilineThreshold?, depth?)

Convert a single value to its UZON text representation.

function stringifyValue(value: any, indent?: string, multilineThreshold?: number, depth?: number): string;
import { stringifyValue } from "@uzon/uzon";

stringifyValue(42n);          // "42"
stringifyValue(3.14);         // "3.14"
stringifyValue("hello");      // '"hello"'
stringifyValue([1n, 2n, 3n]); // "[1, 2, 3]"

stringifyFile(filePath, bindings, options?)

Write UZON bindings to a file.

function stringifyFile(filePath: string, bindings: Record<string, UzonValue>, options?: StringifyOptions): void;
import { parse, stringifyFile } from "@uzon/uzon";

const config = parse('host is "localhost"\nport is 8080');
stringifyFile("output.uzon", config);

StringifyOptions

interface StringifyOptions {
  indent?: string;                               // Indentation per level (default: "    ")
  multilineThreshold?: number;                   // Inline structs up to N fields (default: 1)
  listElementTypes?: WeakMap<UzonValue[], string>; // List element type metadata
}

Type Conversion

toJS(value, options?)

Convert a UzonValue to a plain JS value.

function toJS(value: UzonValue, options?: ToJSOptions): any;
import { parse, toJS } from "@uzon/uzon";

const r = parse('x is 42\ny is 3.14');
toJS(r.x); // 42 (number)
toJS(r.y); // 3.14

ToJSOptions

interface ToJSOptions {
  bigint?: "number" | "bigint" | "string"; // How to convert bigint (default: "number")
}

Type Guards

All type guards return true/false and narrow the TypeScript type.

function isNull(value: UzonValue): value is null;
function isUndefined(value: UzonValue): value is typeof UZON_UNDEFINED;
function isBool(value: UzonValue): value is boolean;
function isInteger(value: UzonValue): value is bigint;
function isFloat(value: UzonValue): value is number;
function isNumber(value: UzonValue): value is number | bigint;
function isString(value: UzonValue): value is string;
function isList(value: UzonValue): value is UzonValue[];
function isTuple(value: UzonValue): value is UzonTuple;
function isEnum(value: UzonValue): value is UzonEnum;
function isUnion(value: UzonValue): value is UzonUnion;
function isTaggedUnion(value: UzonValue): value is UzonTaggedUnion;
function isStruct(value: UzonValue): value is Record<string, UzonValue>;
import { parse, isInteger, isString, isStruct } from "@uzon/uzon";

const r = parse('x is 42\nname is "Alice"\ndb is { host is "localhost" }');

if (isInteger(r.x)) {
  console.log(r.x + 1n); // 43n — TypeScript knows r.x is bigint
}
if (isStruct(r.db)) {
  console.log(r.db.host); // "localhost"
}

Type Narrowing

Safe extraction with type checking. All functions transparently unwrap UzonUnion and UzonTaggedUnion. Throw TypeError on type mismatch.

function asNumber(value: UzonValue): number;   // Accepts integer (→ number) and float
function asInteger(value: UzonValue): bigint;
function asString(value: UzonValue): string;    // Also accepts UzonEnum (→ variant name)
function asBool(value: UzonValue): boolean;
function asList(value: UzonValue): UzonValue[];
function asTuple(value: UzonValue): UzonTuple;
function asStruct(value: UzonValue): Record<string, UzonValue>;
function asEnum(value: UzonValue): UzonEnum;
import { parse, asNumber, asString } from "@uzon/uzon";

const r = parse('port is 8080\nhost is "localhost"');
const port: number = asNumber(r.port); // 8080
const host: string = asString(r.host); // "localhost"

asNumber(r.host); // throws TypeError

Optional Helpers

Like type narrowing, but return undefined instead of throwing on mismatch.

function optionalNumber(value: UzonValue): number | undefined;
function optionalInteger(value: UzonValue): bigint | undefined;
function optionalString(value: UzonValue): string | undefined;
function optionalBool(value: UzonValue): boolean | undefined;
function optionalList(value: UzonValue): UzonValue[] | undefined;
function optionalTuple(value: UzonValue): UzonTuple | undefined;
function optionalStruct(value: UzonValue): Record<string, UzonValue> | undefined;
function optionalEnum(value: UzonValue): UzonEnum | undefined;
import { parse, optionalNumber } from "@uzon/uzon";

const r = parse('port is 8080');
const port = optionalNumber(r.port) ?? 3000; // 8080
const missing = optionalNumber(r.host) ?? 3000; // 3000

Deep Access

Navigate nested values with dot-path syntax. Supports struct fields, list/tuple indexing, and combinations. Transparently unwraps unions and tagged unions at each level.

get(value, path)

Returns undefined if any segment is missing.

function get(value: UzonValue, path: string): UzonValue | undefined;

getOrThrow(value, path)

Throws TypeError if the path doesn't resolve.

function getOrThrow(value: UzonValue, path: string): UzonValue;
import { parse, get, getOrThrow } from "@uzon/uzon";

const r = parse(`
    config is {
        database is {
            host is "localhost"
            port is 5432
        }
        servers is [ "alpha", "beta" ]
        matrix is [[ 1, 2 ], [ 3, 4 ]]
    }
`);

get(r.config, "database.host");   // "localhost"
get(r.config, "servers[0]");      // "alpha"
get(r.config, "matrix[1][0]");    // 3n
get(r.config, "database.missing"); // undefined

getOrThrow(r.config, "database.host");    // "localhost"
getOrThrow(r.config, "database.missing"); // throws TypeError

Pattern Matching

Match on tagged unions and enums by variant.

function match<T>(
  value: UzonValue,
  cases: Record<string, (value: UzonValue) => T> & { _?: (value: UzonValue) => T },
): T;
  • Tagged unions: matches on .tag, passes .value to the handler
  • Enums: matches on .value (variant name), passes the UzonEnum to the handler
  • Unions: unwraps and recurses
  • Use _ as a default/fallback handler
  • Throws TypeError if no match and no _ handler
import { parse, match, asString } from "@uzon/uzon";

// Enum matching
const r = parse('color is red from red, green, blue');
const hex = match(r.color, {
  red:   () => "#ff0000",
  green: () => "#00ff00",
  blue:  () => "#0000ff",
});
// "#ff0000"

// Tagged union matching
const r2 = parse('status is "ok" named success from success as string, failure as string');
const msg = match(r2.status, {
  success: (v) => `Success: ${asString(v)}`,
  failure: (v) => `Error: ${asString(v)}`,
});

// Default handler
const result = match(r.color, {
  red: () => "primary",
  _:   () => "other",
});

JSON Interop

toJSON(value, options?)

Convert a UzonValue to a JSON-safe value (safe for JSON.stringify).

function toJSON(value: UzonValue, options?: ToJSONOptions): JSONValue;
  • bigintnumber (default) or "string". Unsafe bigints (> Number.MAX_SAFE_INTEGER) automatically become strings.
  • NaN / Infinitynull (default) or "string" representation
  • UzonEnumstring (variant name)
  • UzonTaggedUnion{ _tag: string, _value: JSONValue }
  • UzonTuplearray

fromJSON(value)

Convert a JSON-compatible value back to UzonValue.

function fromJSON(value: any): UzonValue;
  • Safe integers → bigint
  • Non-integer numbers → number
  • Objects with _tag and _valueUzonTaggedUnion (roundtrip support)
  • Arrays → UzonValue[]
  • Objects → Record<string, UzonValue>

ToJSONOptions

interface ToJSONOptions {
  bigint?: "number" | "string";      // bigint handling (default: "number")
  nonFinite?: "null" | "string";     // NaN/Infinity handling (default: "null")
}
import { parse, toJSON, fromJSON } from "@uzon/uzon";

const r = parse('x is 42\ny is inf\ncolor is red from red, green, blue');

toJSON(r.x);     // 42
toJSON(r.y);     // null
toJSON(r.color); // "red"

toJSON(r.y, { nonFinite: "string" }); // "Infinity"

// Roundtrip
const json = toJSON(r.x);
const back = fromJSON(json); // 42n

Merge

Deep merge for layered configuration (base + overrides).

merge(base, override)

Deep merge two binding records. Struct fields are merged recursively; non-struct values are replaced. Returns a new object — inputs are not mutated.

function merge(
  base: Record<string, UzonValue>,
  override: Record<string, UzonValue>,
): Record<string, UzonValue>;

mergeValues(base, override)

Merge two individual UzonValue values. Structs are merged recursively; everything else is replaced by the override.

function mergeValues(base: UzonValue, override: UzonValue): UzonValue;
import { parse, merge } from "@uzon/uzon";

const base = parse(`
    database is {
        host is "localhost"
        port is 5432
    }
    debug is false
`);

const prod = parse(`
    database is {
        host is "prod-db.example.com"
    }
    debug is false
`);

const config = merge(base, prod);
// database.host → "prod-db.example.com" (overridden)
// database.port → 5432n (preserved from base)
// debug → false

Builder

Create UZON values from plain JavaScript without writing UZON syntax.

uzon(object)

Auto-convert a plain JS object. Integer numbers become bigint, nested objects become structs, arrays become lists.

import { uzon } from "@uzon/uzon";

const config = uzon({
  host: "localhost",
  port: 8080,            // → 8080n (bigint)
  rate: 3.14,            // stays number (float)
  tags: ["api", "v2"],   // → list
  db: { port: 5432 },    // → struct
});

uzon`...` (tagged template literal)

Write UZON syntax inline with JS interpolation.

import { uzon } from "@uzon/uzon";

const host = "localhost";
const port = 8080;

const config = uzon`
    host is ${host}
    port is ${port}
    color is red from red, green, blue
`;

Factory Helpers

uzon.int(value: number | bigint): bigint

Create an integer value.

uzon.float(value: number): ExplicitFloat

Force a float, even for integer-valued numbers. Without this, uzon({ rate: 60 }) would produce 60n (bigint). Use uzon({ rate: uzon.float(60) }) to keep it as 60 (number).

uzon.enum(variant: string, variants: string[], typeName?: string): UzonEnum

Create an enum value.

uzon.tuple(...elements: JSInput[]): UzonTuple

Create a tuple. Elements are auto-converted.

uzon.tagged(tag: string, value: JSInput, variants: Record<string, string | null>, typeName?: string): UzonTaggedUnion

Create a tagged union.

uzon.union(value: JSInput, types: string[], typeName?: string): UzonUnion

Create an untagged union.

uzon.list(...elements: JSInput[]): UzonValue[]

Create a list. Elements are auto-converted.

uzon.struct(obj: Record<string, JSInput>): Record<string, UzonValue>

Create a struct. Values are auto-converted.

uzon.value(value: JSInput): UzonValue

Auto-convert a single value.

import { uzon } from "@uzon/uzon";

const config = uzon({
  host: "localhost",
  port: 8080,
  rate: uzon.float(60),
  color: uzon.enum("red", ["red", "green", "blue"], "Color"),
  point: uzon.tuple(10, 20),
  status: uzon.tagged("ok", "success", { ok: "string", err: "string" }),
});

Immutable Updates

All update functions return new values — originals are never mutated.

Struct Updates

function withField(struct: Record<string, UzonValue>, key: string, value: UzonValue): Record<string, UzonValue>;
function withoutField(struct: Record<string, UzonValue>, key: string): Record<string, UzonValue>;
import { parse, withField, withoutField } from "@uzon/uzon";

const config = parse('host is "localhost"\nport is 8080\ndebug is true');

const updated = withField(config, "port", 3000n);
// { host: "localhost", port: 3000n, debug: true }

const removed = withoutField(config, "debug");
// { host: "localhost", port: 8080n }

List Updates

function append(list: UzonValue[], value: UzonValue): UzonValue[];
function prepend(list: UzonValue[], value: UzonValue): UzonValue[];
function setAt(list: UzonValue[], index: number, value: UzonValue): UzonValue[];   // throws RangeError
function removeAt(list: UzonValue[], index: number): UzonValue[];                   // throws RangeError
import { append, prepend, setAt, removeAt } from "@uzon/uzon";

const list = [1n, 2n, 3n];

append(list, 4n);     // [1n, 2n, 3n, 4n]
prepend(list, 0n);    // [0n, 1n, 2n, 3n]
setAt(list, 1, 99n);  // [1n, 99n, 3n]
removeAt(list, 0);    // [2n, 3n]

Tuple Updates

function tupleSetAt(tuple: UzonTuple, index: number, value: UzonValue): UzonTuple; // throws RangeError

Display

displayValue(value)

Human-readable display of any UzonValue. Useful for debugging and logging.

function displayValue(value: UzonValue): string;
import { parse, displayValue, UzonTuple } from "@uzon/uzon";

displayValue(42n);                            // "42"
displayValue("hello");                        // '"hello"'
displayValue([1n, 2n, 3n]);                   // "[1, 2, 3]"
displayValue({ a: 1n, b: "hi" });             // '{ a: 1, b: "hi" }'
displayValue(new UzonTuple([1n, "a", true])); // '(1, "a", true)'

Compound types also support toString():

const t = new UzonTuple([1n, 2n, 3n]);
`${t}`; // "(1, 2, 3)"

const f = new UzonFunction(["x"], ["i32"], [null], "i32", ...);
`${f}`; // "fn(x: i32) -> i32"

Watch

Watch a UZON file for changes and re-parse on modification.

function watch(
  filePath: string,
  callback: (bindings: Record<string, UzonValue>) => void,
  options?: WatchOptions,
): () => void; // returns cleanup function

WatchOptions

interface WatchOptions {
  debounce?: number;                    // Debounce interval in ms (default: 100)
  interval?: number;                    // Polling interval in ms (default: 1000)
  immediate?: boolean;                  // Invoke callback immediately (default: true)
  onError?: (error: Error) => void;     // Called on parse errors
  env?: Record<string, string>;         // Environment variables
}
import { watch } from "@uzon/uzon";

const stop = watch("config.uzon", (config) => {
  console.log("Config reloaded:", config);
}, {
  onError: (err) => console.error("Parse error:", err.message),
});

// Later: stop watching
stop();

Value Classes

UzonEnum

class UzonEnum {
  constructor(value: string, variants: readonly string[], typeName?: string | null);

  readonly value: string;                   // Selected variant
  readonly variants: readonly string[];     // All variants
  readonly typeName: string | null;         // Type name (if named)

  valueOf(): string;    // Returns variant name
  toString(): string;   // Returns variant name
}

UzonUnion

class UzonUnion {
  constructor(value: UzonValue, types: readonly string[], typeName?: string | null);

  readonly value: UzonValue;            // Inner value
  readonly types: readonly string[];    // Possible type names
  readonly typeName: string | null;

  valueOf(): UzonValue;  // Returns inner value
  toString(): string;    // String representation of inner value
}

UzonTaggedUnion

class UzonTaggedUnion {
  constructor(value: UzonValue, tag: string, variants: ReadonlyMap<string, string | null>, typeName?: string | null);

  readonly value: UzonValue;                             // Inner value
  readonly tag: string;                                  // Variant tag
  readonly variants: ReadonlyMap<string, string | null>; // Tag → payload type
  readonly typeName: string | null;

  valueOf(): UzonValue;  // Returns inner value
  toString(): string;    // String representation of inner value
}

UzonTuple

class UzonTuple {
  constructor(elements: readonly UzonValue[]);

  readonly elements: readonly UzonValue[];
  readonly length: number;

  [Symbol.iterator](): Iterator<UzonValue>;  // Iterable
  toString(): string;                        // e.g. "(1, 2, 3)"
}

UzonFunction

class UzonFunction {
  constructor(
    paramNames: readonly string[],
    paramTypes: readonly string[],
    defaultValues: readonly (UzonValue | null)[],
    returnType: string,
    body: unknown,
    finalExpr: unknown,
    closureScope: unknown,
    typeName?: string | null,
  );

  readonly paramNames: readonly string[];
  readonly paramTypes: readonly string[];
  readonly defaultValues: readonly (UzonValue | null)[];
  readonly returnType: string;
  readonly typeName: string | null;

  toString(): string;  // e.g. "fn(x: i32, y: i32) -> i32"
}

UZON_UNDEFINED

const UZON_UNDEFINED: unique symbol;
type UzonUndefined = typeof UZON_UNDEFINED;

Sentinel for unresolved lookups (e.g. unresolved identifiers, env.UNSET). Not a valid value — propagates through member access but causes errors in operations.


Errors

All UZON errors extend UzonError and carry source location information.

class UzonError extends Error {
  readonly line?: number;
  readonly col?: number;
  filename?: string;
  readonly importTrace: ImportFrame[];

  withFilename(filename: string): this;
  addImportFrame(filename: string, line: number, col: number): this;
}

class UzonSyntaxError extends UzonError {}   // Lexical/grammatical violations
class UzonTypeError extends UzonError {}     // Type annotation mismatches
class UzonRuntimeError extends UzonError {}  // Undefined access, overflow, division by zero, etc.
class UzonCircularError extends UzonError {} // Circular dependency between bindings

interface ImportFrame {
  filename: string;
  line: number;
  col: number;
}
import { parse, UzonSyntaxError } from "@uzon/uzon";

try {
  parse('x is is is');
} catch (e) {
  if (e instanceof UzonSyntaxError) {
    console.log(`${e.line}:${e.col}: ${e.message}`);
  }
}

Low-Level API

For advanced use cases, the lexer, parser, and evaluator are exposed directly.

import { Lexer, Parser, Evaluator } from "@uzon/uzon";

const tokens = new Lexer(source).tokenize();
const ast = new Parser(tokens).parse();
const bindings = new Evaluator({ env: process.env }).evaluate(ast);

Lexer

class Lexer {
  constructor(src: string);
  tokenize(): Token[];
}

Parser

class Parser {
  constructor(tokens: Token[]);
  parse(): DocumentNode;
}

Evaluator

class Evaluator {
  constructor(options?: EvalOptions);
  evaluate(doc: DocumentNode): Record<string, UzonValue>;
}

EvalOptions

interface EvalOptions {
  env?: Record<string, string>;
  filename?: string;
  fileReader?: (path: string) => string;
  importCache?: Map<string, Record<string, UzonValue>>;
  scopeCache?: Map<string, Scope>;
  importStack?: string[];
}

Scope

class Scope {
  constructor(parent?: Scope | null);

  set(name: string, value: UzonValue): void;
  get(name: string, exclude?: string): UzonValue | typeof UZON_UNDEFINED;
  has(name: string): boolean;
  hasOwn(name: string): boolean;
  ownBindingNames(): string[];
  setType(name: string, def: TypeDef): void;
}

TypeDef

Type definition stored in a Scope. Used by the evaluator for type checking and annotation resolution.

interface TypeDef {
  kind: "enum" | "union" | "tagged_union" | "struct" | "list" | "primitive" | "function";
  name: string;
  variants?: string[];                     // Enum variant names
  variantTypes?: Map<string, string>;      // Tagged union: tag → payload type
  memberTypes?: string[];                  // Union member type names
  fields?: Map<string, string>;            // Struct: field → type tag
  fieldAnnotations?: Map<string, string>;  // Struct: per-field type annotations
  elementType?: string;                    // List element type
  paramTypes?: string[];                   // Function parameter types
  returnType?: string;                     // Function return type
}

AST Types

// Top-level document
interface DocumentNode { kind: "Document"; bindings: BindingNode[]; line: number; col: number; }

// A named binding: `name is value`
interface BindingNode { kind: "Binding"; name: string; value: AstNode; line: number; col: number; }

// All binary operators
type BinaryOp =
  | "+" | "-" | "*" | "/" | "%" | "^" | "++" | "**"
  | "<" | "<=" | ">" | ">="
  | "and" | "or"
  | "is" | "is not" | "is named" | "is not named"
  | "is type" | "is not type"
  | "in";

// AstNode is a discriminated union of all expression node types
type AstNode = IntegerLiteralNode | FloatLiteralNode | StringLiteralNode | BoolLiteralNode
  | NullLiteralNode | IdentifierNode | BinaryOpNode | UnaryOpNode | IfExprNode
  | StructLiteralNode | ListLiteralNode | TupleLiteralNode | /* ... and more */;

TokenType (enum)

Covers all UZON token types: Integer, Float, String, True, False, Null, Identifier, Is, Are, From, Called, As, Named, With, PlusKw, Type, To, Of, And, Or, Not, If, Then, Else, Case, When, Env, Struct, In, Function, Returns, Default, OrElse, IsNot, IsNamed, IsNotNamed, IsType, IsNotType, Plus, Minus, Star, Slash, LBrace, RBrace, LBracket, RBracket, LParen, RParen, Comma, Dot, At, Newline, Eof, and more.

formatUzonFloat(value)

Format a number as a UZON float literal (shortest round-trip form, always includes a decimal point).

function formatUzonFloat(value: number): string;
formatUzonFloat(42);       // "42.0"
formatUzonFloat(3.14);     // "3.14"
formatUzonFloat(Infinity); // "inf"
formatUzonFloat(NaN);      // "nan"

Iteration

UZON compound types support standard JS iteration:

import { parse } from "@uzon/uzon";

const r = parse('items is [1, 2, 3]\npoint is (10, 20)');

// Lists are arrays — all array methods work
for (const item of r.items as any[]) { ... }

// Tuples are iterable via Symbol.iterator
for (const elem of r.point as UzonTuple) { ... }

// Structs are plain objects — use Object.entries
for (const [key, value] of Object.entries(r)) { ... }

License

MIT