ASTDiscriminated union of all AST node types.
Details
Every Schema has an .ast property of this type. Use the guard functions
(isString, isObjects, etc.) to narrow to a specific variant,
then access variant-specific fields.
- All variants share the Base fields:
annotations,checks,encoding,context. - Discriminate on the
_tagfield (e.g."String","Objects","Union").
export type type AST =
| Declaration
| Null
| Undefined
| Void
| Never
| Unknown
| Any
| String
| Number
| Boolean
| BigInt
| Symbol
| Literal
| UniqueSymbol
| ObjectKeyword
| Enum
| TemplateLiteral
| Arrays
| Objects
| Union<AST>
| Suspend
Discriminated union of all AST node types.
Details
Every Schema has an .ast property of this type. Use the guard functions
(
isString
,
isObjects
, etc.) to narrow to a specific variant,
then access variant-specific fields.
- All variants share the
Base
fields:
annotations, checks,
encoding, context.
- Discriminate on the
_tag field (e.g. "String", "Objects", "Union").
AST =
| class Declarationclass Declaration {
_tag: 'Declaration';
typeParameters: ReadonlyArray<AST>;
run: (typeParameters: ReadonlyArray<AST>) => (input: unknown, self: Declaration, options: ParseOptions) => Effect.Effect<any, SchemaIssue.Issue, any>;
encodingChecks: Checks | undefined;
getParser: () => SchemaParser.Parser;
_rebuild: (recur: (ast: AST) => AST, checks: Checks | undefined, encodingChecks: Checks | undefined) => Declaration;
recur: (recur: (ast: AST) => AST) => Declaration;
flip: (recur: (ast: AST) => AST) => Declaration;
getExpected: () => string;
annotations: Schema.Annotations.Annotations | undefined;
checks: Checks | undefined;
encoding: Encoding | undefined;
context: Context | undefined;
toString: () => string;
}
AST node for user-defined opaque types with custom parsing logic.
When to use
Use when you need a custom schema AST node because none of the built-in
nodes fit.
Details
typeParameters — inner schemas this declaration is parameterized over
(e.g. the element type for a custom collection).
run — factory that receives typeParameters and returns a parser that
validates or transforms raw input.
Declaration
| class Nullclass Null {
_tag: 'Null';
getParser: () => SchemaParser.Parser;
getExpected: () => string;
annotations: Schema.Annotations.Annotations | undefined;
checks: Checks | undefined;
encoding: Encoding | undefined;
context: Context | undefined;
toString: () => string;
}
AST node matching the null literal value.
Details
Parsing succeeds only when the input is exactly null.
Null
| class Undefinedclass Undefined {
_tag: 'Undefined';
getParser: () => SchemaParser.Parser;
toCodecJson: () => AST;
getExpected: () => string;
annotations: Schema.Annotations.Annotations | undefined;
checks: Checks | undefined;
encoding: Encoding | undefined;
context: Context | undefined;
toString: () => string;
}
AST node matching the undefined value.
Details
Parsing succeeds only when the input is exactly undefined.
Undefined
| class Voidclass Void {
_tag: 'Void';
getParser: () => SchemaParser.Parser;
toCodecJson: () => AST;
getExpected: () => string;
annotations: Schema.Annotations.Annotations | undefined;
checks: Checks | undefined;
encoding: Encoding | undefined;
context: Context | undefined;
toString: () => string;
}
AST node matching TypeScript void return-value semantics.
When to use
Use when you need an AST node for a value whose result is intentionally
ignored.
Details
Parsers built from this node accept any present runtime input and map it to
undefined. Public schemas built from it may still expose void as their
typed decoded and encoded representation.
Void
| class Neverclass Never {
_tag: 'Never';
getParser: () => SchemaParser.Parser;
getExpected: () => string;
annotations: Schema.Annotations.Annotations | undefined;
checks: Checks | undefined;
encoding: Encoding | undefined;
context: Context | undefined;
toString: () => string;
}
AST node representing the never type — no value matches.
Details
Parsing always fails. Useful as a placeholder in unions or as the result
of narrowing that eliminates all options.
Never
| class Unknownclass Unknown {
_tag: 'Unknown';
getParser: () => SchemaParser.Parser;
getExpected: () => string;
annotations: Schema.Annotations.Annotations | undefined;
checks: Checks | undefined;
encoding: Encoding | undefined;
context: Context | undefined;
toString: () => string;
}
AST node representing the unknown type — every value matches.
Details
Unlike
Any
, this is type-safe: the parsed result is typed as
unknown rather than any.
Unknown
| class Anyclass Any {
_tag: 'Any';
getParser: () => SchemaParser.Parser;
getExpected: () => string;
annotations: Schema.Annotations.Annotations | undefined;
checks: Checks | undefined;
encoding: Encoding | undefined;
context: Context | undefined;
toString: () => string;
}
AST node representing the any type — every value matches.
Any
| class Stringclass String {
_tag: 'String';
getParser: () => SchemaParser.Parser;
matchPart: (s: string, options: ParseOptions) => string | undefined;
getExpected: () => string;
annotations: Schema.Annotations.Annotations | undefined;
checks: Checks | undefined;
encoding: Encoding | undefined;
context: Context | undefined;
toString: () => string;
}
AST node matching any string value.
String
| class Numberclass Number {
_tag: 'Number';
getParser: () => SchemaParser.Parser;
matchKey: (s: string, options: ParseOptions) => number | undefined;
matchPart: (s: string, options: ParseOptions) => number | undefined;
_match: (regexp: RegExp, s: string, options: ParseOptions) => number | undefined;
toCodecJson: () => AST;
toCodecStringTree: () => AST;
getExpected: () => string;
annotations: Schema.Annotations.Annotations | undefined;
checks: Checks | undefined;
encoding: Encoding | undefined;
context: Context | undefined;
toString: () => string;
}
AST node matching any number value (including NaN, Infinity,
-Infinity).
Details
Default JSON serialization:
- Finite numbers are serialized as JSON numbers.
Infinity, -Infinity, and NaN are serialized as JSON strings.
If the node has an isFinite or isInt check, the string fallback is
skipped since non-finite values cannot occur.
Number
| class Booleanclass Boolean {
_tag: 'Boolean';
getParser: () => SchemaParser.Parser;
getExpected: () => string;
annotations: Schema.Annotations.Annotations | undefined;
checks: Checks | undefined;
encoding: Encoding | undefined;
context: Context | undefined;
toString: () => string;
}
AST node matching any boolean value (true or false).
Boolean
| class BigIntclass BigInt {
_tag: 'BigInt';
getParser: () => SchemaParser.Parser;
matchPart: (s: string, options: ParseOptions) => bigint | undefined;
toCodecStringTree: () => AST;
getExpected: () => string;
annotations: Schema.Annotations.Annotations | undefined;
checks: Checks | undefined;
encoding: Encoding | undefined;
context: Context | undefined;
toString: () => string;
}
AST node matching any bigint value.
Details
When serialized to a string-based codec, bigints are converted to/from
their decimal string representation.
BigInt
| class Symbolclass Symbol {
_tag: 'Symbol';
getParser: () => SchemaParser.Parser;
matchKey: (s: symbol, options: ParseOptions) => symbol | undefined;
toCodecStringTree: () => AST;
getExpected: () => string;
annotations: Schema.Annotations.Annotations | undefined;
checks: Checks | undefined;
encoding: Encoding | undefined;
context: Context | undefined;
toString: () => string;
}
AST node matching any symbol value.
When to use
Use when you need the AST node class for schemas that match any JavaScript
symbol value.
Details
When serialized to a string-based codec, symbols are converted via
Symbol.keyFor and must be registered with Symbol.for.
Symbol
| class Literalclass Literal {
_tag: 'Literal';
literal: LiteralValue;
getParser: () => SchemaParser.Parser;
matchPart: (s: string, _options: ParseOptions) => LiteralValue | undefined;
toCodecJson: () => AST;
toCodecStringTree: () => AST;
getExpected: () => string;
annotations: Schema.Annotations.Annotations | undefined;
checks: Checks | undefined;
encoding: Encoding | undefined;
context: Context | undefined;
toString: () => string;
}
AST node matching an exact primitive value (string, number, boolean, or
bigint).
Details
Parsing succeeds only when the input is strictly equal (===) to the
stored literal. Numeric literals must be finite — Infinity, -Infinity,
and NaN are rejected at construction time.
Example (Creating a literal AST)
import { SchemaAST } from "effect"
const ast = new SchemaAST.Literal("active")
console.log(ast.literal) // "active"
Literal
| class UniqueSymbolclass UniqueSymbol {
_tag: 'UniqueSymbol';
symbol: symbol;
getParser: () => SchemaParser.Parser;
toCodecStringTree: () => AST;
getExpected: () => string;
annotations: Schema.Annotations.Annotations | undefined;
checks: Checks | undefined;
encoding: Encoding | undefined;
context: Context | undefined;
toString: () => string;
}
AST node matching a specific unique symbol value.
Details
Parsing succeeds only when the input is reference-equal to the stored
symbol.
UniqueSymbol
| class ObjectKeywordclass ObjectKeyword {
_tag: 'ObjectKeyword';
getParser: () => SchemaParser.Parser;
getExpected: () => string;
annotations: Schema.Annotations.Annotations | undefined;
checks: Checks | undefined;
encoding: Encoding | undefined;
context: Context | undefined;
toString: () => string;
}
AST node matching the TypeScript object type — accepts objects, arrays,
and functions (anything non-primitive and non-null).
ObjectKeyword
| class Enumclass Enum {
_tag: 'Enum';
enums: ReadonlyArray<readonly [string, string | number]>;
getParser: () => SchemaParser.Parser;
toCodecStringTree: () => AST;
getExpected: () => string;
annotations: Schema.Annotations.Annotations | undefined;
checks: Checks | undefined;
encoding: Encoding | undefined;
context: Context | undefined;
toString: () => string;
}
AST node representing a TypeScript enum.
Details
Holds enums as an array of [name, value] pairs where values are
string | number. Parsing succeeds when the input matches any enum value.
Enum
| class TemplateLiteralclass TemplateLiteral {
_tag: 'TemplateLiteral';
parts: ReadonlyArray<AST>;
encodedParts: ReadonlyArray<TemplateLiteralPart>;
getParser: (recur: (ast: AST) => SchemaParser.Parser) => SchemaParser.Parser;
getExpected: () => string;
matchPart: (s: string, options: ParseOptions) => string | undefined;
asTemplateLiteralParser: () => Arrays;
annotations: Schema.Annotations.Annotations | undefined;
checks: Checks | undefined;
encoding: Encoding | undefined;
context: Context | undefined;
toString: () => string;
}
AST node representing a TypeScript template literal type
(e.g. `user_${string}`).
Details
parts is an array of AST nodes; each part contributes to matching
strings at runtime.
TemplateLiteral
| class Arraysclass Arrays {
_tag: 'Arrays';
isMutable: boolean;
elements: ReadonlyArray<AST>;
rest: ReadonlyArray<AST>;
encodingChecks: Checks | undefined;
getParser: (recur: (ast: AST) => SchemaParser.Parser) => SchemaParser.Parser;
_rebuild: (recur: (ast: AST) => AST, checks: Checks | undefined, encodingChecks: Checks | undefined) => Arrays;
recur: (recur: (ast: AST) => AST) => Arrays;
flip: (recur: (ast: AST) => AST) => Arrays;
getExpected: () => string;
annotations: Schema.Annotations.Annotations | undefined;
checks: Checks | undefined;
encoding: Encoding | undefined;
context: Context | undefined;
toString: () => string;
}
AST node for array-like types — both tuples and arrays.
When to use
Use when constructing or inspecting AST nodes for tuple or array-like schemas,
including rest elements.
Details
elements — positional element types (tuple elements). An element is
optional if its
Context.isOptional
is true.
rest — the rest/variadic element types. When non-empty, the first
entry is the "spread" type (e.g. ...Array<string>), and subsequent
entries are trailing positional elements after the spread.
isMutable — whether the resulting array is readonly (false) or
mutable (true).
Gotchas
Construction enforces TypeScript ordering rules: a required element
cannot follow an optional one, and an optional element cannot follow a
rest element.
Example (Inspecting a tuple AST)
import { Schema, SchemaAST } from "effect"
const schema = Schema.Tuple([Schema.String, Schema.Number])
const ast = schema.ast
if (SchemaAST.isArrays(ast)) {
console.log(ast.elements.length) // 2
console.log(ast.rest.length) // 0
}
Arrays
| class Objectsclass Objects {
_tag: 'Objects';
propertySignatures: ReadonlyArray<PropertySignature>;
indexSignatures: ReadonlyArray<IndexSignature>;
encodingChecks: Checks | undefined;
getParser: (recur: (ast: AST) => SchemaParser.Parser) => SchemaParser.Parser;
_rebuild: (recur: (ast: AST) => AST, recurParameter: (ast: AST) => AST, flipMerge: boolean, checks: Checks | undefined, encodingChecks: Checks | undefined) => Objects;
flip: (recur: (ast: AST) => AST) => AST;
recur: (recur: (ast: AST) => AST, recurParameter?: (ast: AST) => AST) => AST;
getExpected: () => string;
annotations: Schema.Annotations.Annotations | undefined;
checks: Checks | undefined;
encoding: Encoding | undefined;
context: Context | undefined;
toString: () => string;
}
AST node for object-like schemas, including structs and records.
When to use
Use when constructing or inspecting AST nodes for structs or records rather
than array-like schemas.
Details
propertySignatures — named properties with their types (struct fields).
indexSignatures — index signature entries (record patterns), each with
a parameter AST for matching keys and a type AST for values.
An Objects node with no properties and no index signatures performs only a
non-nullish check: it accepts any value except null and undefined,
including primitive values.
Gotchas
Duplicate property names throw at construction time.
Example (Inspecting a struct AST)
import { Schema, SchemaAST } from "effect"
const schema = Schema.Struct({ name: Schema.String })
const ast = schema.ast
if (SchemaAST.isObjects(ast)) {
for (const ps of ast.propertySignatures) {
console.log(ps.name, ps.type._tag)
}
// "name" "String"
}
Objects
| class Union<A extends AST = AST>class Union {
_tag: 'Union';
types: ReadonlyArray<A>;
mode: "anyOf" | "oneOf";
encodingChecks: Checks | undefined;
getParser: (recur: (ast: AST) => SchemaParser.Parser) => SchemaParser.Parser;
_rebuild: (recur: (ast: AST) => AST, checks: Checks | undefined, encodingChecks: Checks | undefined) => Union<AST>;
recur: (recur: (ast: AST) => AST) => Union<AST>;
flip: (recur: (ast: AST) => AST) => Union<AST>;
matchPart: (s: string, options: ParseOptions) => LiteralValue | undefined;
getExpected: (getExpected: (ast: AST) => string) => string;
annotations: Schema.Annotations.Annotations | undefined;
checks: Checks | undefined;
encoding: Encoding | undefined;
context: Context | undefined;
toString: () => string;
}
AST node representing a union of schemas.
Details
types — the member AST nodes.
mode — "anyOf" succeeds on the first match (like TypeScript unions);
"oneOf" requires exactly one member to match (fails if multiple do).
During parsing, members are tried in order. An internal candidate index
narrows which members to try based on the runtime type of the input and
discriminant ("sentinel") fields, making large unions efficient.
Example (Inspecting a union AST)
import { Schema, SchemaAST } from "effect"
const schema = Schema.Union([Schema.String, Schema.Number])
const ast = schema.ast
if (SchemaAST.isUnion(ast)) {
console.log(ast.types.length) // 2
console.log(ast.mode) // "anyOf"
}
Union
| class Suspendclass Suspend {
_tag: 'Suspend';
thunk: () => AST;
getParser: (recur: (ast: AST) => SchemaParser.Parser) => SchemaParser.Parser;
recur: (recur: (ast: AST) => AST) => Suspend;
getExpected: (getExpected: (ast: AST) => string) => string;
annotations: Schema.Annotations.Annotations | undefined;
checks: Checks | undefined;
encoding: Encoding | undefined;
context: Context | undefined;
toString: () => string;
}
AST node for lazy/recursive schemas.
Details
Wraps a thunk (() => AST) that is memoized on first call. Use this to
define recursive or mutually recursive schemas without infinite loops at
construction time.
Example (Defining recursive schema ASTs)
import { Schema, SchemaAST } from "effect"
interface Category {
readonly name: string
readonly children: ReadonlyArray<Category>
}
const Category = Schema.Struct({
name: Schema.String,
children: Schema.Array(Schema.suspend((): Schema.Codec<Category> => Category))
})
// The recursive branch is a Suspend node
Suspend