Defjs

struct facade, Infer, and StructError.

Struct

Build wire-boundary shapes, parse values, infer TypeScript types.

struct

Facade. Prefer this over internal constructors.

const User = struct.object({
  id: struct.number(),
  displayName: struct.string().alias("display_name"),
});

function readUser() {
  const [error, user] = struct.parse(User, { id: 1, displayName: "Ada" });
  if (error) {
    console.error(error.message);
    return;
  }
  console.log(user.displayName);
}

readUser();

Primitives and containers

HelperRole
struct.string() / number() / boolean() / bigint()Scalars
struct.literal(value)Exact literal
struct.null() / any() / unknown()Null / any / unknown. any() and unknown() reject null and undefined
struct.date()Date
struct.array(item) / tuple(items) / record(value)Collections. tuple takes one array: struct.tuple([a, b])
struct.object(shape)Object; fields accept .optional(), .null() / .nullable(), .alias(name)
struct.or(...) / intersection(...) / discriminatedUnion(tag, options)Unions
struct.enum(values)String list or { Name: value } map; the map accepts its values, not its keys

Body codecs and binary values

HelperRole
struct.formData(shape) / urlencoded(shape)Object struct plus a codec tag. The tag applies only when that value is the request body root
struct.arrayBuffer() / blob() / file()Binary values. As a body root they are sent as bytes; as output / error they select that representation
struct.string()Text. As an HTTP or SSE body root, or as HTTP/SSE inbound data, the bytes stay text. A WebSocket incoming frame is JSON-parsed first, so a string struct expects a JSON string

struct.parse()

function parse<
  S extends StructLike<unknown, unknown, boolean>,
>(
  struct: S,
  value: unknown,
  options?: { aliases?: boolean; errorMap?: ErrorMap },
): ParseResult<S["_struct"]["output"]>;
  • Returns [null, value] or [StructError, undefined]. The error carries one issue. Object fields stop at the first bad field. struct.or tries every branch and then reports invalid_union; it does not keep the first branch failure.
  • Object fields are required unless marked .optional() or .nullish(). Keys the shape does not declare are dropped from the result.
  • Optional options.errorMap rewrites issue messages for this parse only.
  • Default reads logical keys (displayName). Pass { aliases: true } to read wire keys (display_name) the same way HTTP/JSON codecs do.

ErrorMap

type ErrorMap = (issue: StructIssue) => string | undefined;

Types

Infer

StructInput

AnyStruct

ParseResult

type Infer<T> = StructOutput<T>;

type StructInput<T> = T extends {
  readonly _struct: { readonly input: unknown };
}
  ? T["_struct"]["input"]
  : never;

type AnyStruct = Struct<any, any, boolean>;

type ParseResult<O> =
  [error: null, value: O] | [error: StructError, value: undefined];

StructError

class StructError extends Error {
  readonly issues: StructIssue[];
  constructor(issues: StructIssue[]);
  format(): FormattedStructError;
  flatten(): FlattenedStructError;
  prettify(): string;
}

StructIssue: path, code, expected, received, message. code is custom, invalid_enum, invalid_intersection, invalid_literal, invalid_type, invalid_union, or missing_key.

See Struct guide.

STRUCT

A unique symbol that tags the objects parsed from endpoint input. It is internal to the outbound encoder and is exported as a type only. Do not read or set it.

Struct

A parseable shape: input/output types plus .optional(), .null() / .nullable(), .nullish(), .alias().

StructLike

Anything with a _struct type payload. See StructLike.

StructMethods

.alias(), .null() / .nullable(), .nullish(), .optional().

ObjectStruct

Object-shaped struct from struct.object.

StructIssue

path, code, expected, received, message. code is custom, invalid_enum, invalid_intersection, invalid_literal, invalid_type, invalid_union, or missing_key.

FormattedStructError

Nested { _errors, [key]: … } tree from StructError.format().

FlattenedStructError

formErrors plus fieldErrors from StructError.flatten().

Edit this page on GitHub
Released under the MIT License. · Copyright © 2026 MunMunMiao

On this page