(
keySchema: Constraint,
annotations?: Annotations.Filter
): SchemaAST.Filter<object>Validates that every own property key of an object satisfies the encoded side of the provided key schema.
Details
This check uses Reflect.ownKeys, so symbol keys are validated in addition to
string property names.
JSON Schema:
For string property names, this corresponds to the propertyNames constraint
in JSON Schema.
export function function isPropertyNames(
keySchema: Constraint,
annotations?: Annotations.Filter
): SchemaAST.Filter<object>
Validates that every own property key of an object satisfies the encoded side
of the provided key schema.
Details
This check uses Reflect.ownKeys, so symbol keys are validated in addition to
string property names.
JSON Schema:
For string property names, this corresponds to the propertyNames constraint
in JSON Schema.
isPropertyNames(keySchema: Constraint(parameter) keySchema: {
ast: SchemaAST.AST;
Type: unknown;
Encoded: unknown;
DecodingServices: unknown;
EncodingServices: unknown;
Iso: unknown;
}
keySchema: Constraint, annotations: Annotations.Filter | undefinedannotations?: Annotations.interface Annotations.FilterAnnotations for filter schema nodes (created via Schema.filter). Extends
Augment
with an optional error message, identifier, and metadata.
Filters are intentionally non-parametric to keep them covariant.
Filter) {
const const propertyNames: toEncoded<Constraint>const propertyNames: {
Type: S["Encoded"];
Encoded: S["Encoded"];
DecodingServices: never;
EncodingServices: never;
Iso: S["Encoded"];
schema: S;
Rebuild: Rebuild;
ast: Ast;
annotate: (annotations: Annotations.Bottom<unknown, ReadonlyArray<Constraint>>) => toEncoded<Constraint>;
annotateKey: (annotations: Annotations.Key<unknown>) => toEncoded<Constraint>;
check: (checks_0: SchemaAST.Check<unknown>, ...checks: Array<SchemaAST.Check<unknown>>) => toEncoded<Constraint>;
rebuild: (ast: SchemaAST.AST) => toEncoded<Constraint>;
make: (input: unknown, options?: MakeOptions) => unknown;
makeOption: (input: unknown, options?: MakeOptions) => Option_.Option<unknown>;
makeEffect: (input: unknown, options?: MakeOptions) => Effect.Effect<unknown, SchemaError, never>;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
propertyNames = const toEncoded: toEncodedLambda
;<Constraint>(self: Constraint) =>
toEncoded<Constraint>
Type-level representation returned by
toEncoded
.
Extracts the encoded-side schema: sets Type to equal the Encoded,
discarding the decoding transformation path.
toEncoded(keySchema: Constraint(parameter) keySchema: {
ast: SchemaAST.AST;
Type: unknown;
Encoded: unknown;
DecodingServices: unknown;
EncodingServices: unknown;
Iso: unknown;
}
keySchema)
const const parser: (
input: unknown,
options: SchemaAST.ParseOptions
) => SchemaIssue.Issue | undefined
parser = import SchemaParserSchemaParser.function _issue<T>(
ast: SchemaAST.AST
): (
input: unknown,
options: SchemaAST.ParseOptions
) => SchemaIssue.Issue | undefined
_issue(const propertyNames: toEncoded<Constraint>const propertyNames: {
Type: S["Encoded"];
Encoded: S["Encoded"];
DecodingServices: never;
EncodingServices: never;
Iso: S["Encoded"];
schema: S;
Rebuild: Rebuild;
ast: Ast;
annotate: (annotations: Annotations.Bottom<unknown, ReadonlyArray<Constraint>>) => toEncoded<Constraint>;
annotateKey: (annotations: Annotations.Key<unknown>) => toEncoded<Constraint>;
check: (checks_0: SchemaAST.Check<unknown>, ...checks: Array<SchemaAST.Check<unknown>>) => toEncoded<Constraint>;
rebuild: (ast: SchemaAST.AST) => toEncoded<Constraint>;
make: (input: unknown, options?: MakeOptions) => unknown;
makeOption: (input: unknown, options?: MakeOptions) => Option_.Option<unknown>;
makeEffect: (input: unknown, options?: MakeOptions) => Effect.Effect<unknown, SchemaError, never>;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
propertyNames.Bottom<unknown, unknown, unknown, unknown, AST, toEncoded<Constraint>, unknown, unknown, readonly Constraint[], unknown, Mutability, Optionality, ConstructorDefault, Mutability, Optionality>["ast"]: SchemaAST.ASTast)
return const makeFilter: <T>(
filter: (
input: T,
ast: SchemaAST.AST,
options: SchemaAST.ParseOptions
) => FilterOutput,
annotations?: Annotations.Filter | undefined,
abort?: boolean
) => SchemaAST.Filter<T>
Creates a custom validation filter from a predicate function.
Details
The predicate receives the decoded input value, the schema AST, and parse
options, and returns a FilterOutput. Non-success outputs are normalized into
schema issues. The annotations parameter annotates the filter itself; with
the default formatter, failures use message first, expected second, and
<filter> when neither is provided.
When abort is true, parsing stops after this filter fails instead of
collecting later check failures.
Example (Reporting failure at a nested path)
import { Schema } from "effect"
const schema = Schema.Struct({ password: Schema.String, confirmPassword: Schema.String }).check(
Schema.makeFilter((o) =>
o.password === o.confirmPassword
? undefined
: { path: ["password"], issue: "password and confirmPassword must match" }
)
)
console.log(String(Schema.decodeUnknownExit(schema)({ password: "123456", confirmPassword: "1234567" })))
// Failure(Cause([Fail(SchemaError: password and confirmPassword must match
// at ["password"])]))
Example (Reporting multiple failures at once)
import { Schema } from "effect"
const schema = Schema.Struct({ a: Schema.Finite, b: Schema.Finite, c: Schema.Finite }).check(
Schema.makeFilter((o) => {
const issues: Array<Schema.FilterIssue> = []
if (o.a > 0) {
if (o.b <= 0) issues.push({ path: ["b"], issue: "b must be greater than 0" })
if (o.c <= 0) issues.push({ path: ["c"], issue: "c must be greater than 0" })
}
return issues
})
)
console.log(String(Schema.decodeUnknownExit(schema)({ a: 1, b: 0, c: 0 })))
// Failure(Cause([Fail(SchemaError: b must be greater than 0
// at ["b"]
// c must be greater than 0
// at ["c"])]))
makeFilter<object>(
(input: objectinput, ast: SchemaAST.ASTast, options: SchemaAST.ParseOptions(parameter) options: {
errors: "first" | "all" | undefined;
onExcessProperty: "ignore" | "error" | "preserve" | undefined;
propertyOrder: "none" | "original" | undefined;
disableChecks: boolean | undefined;
concurrency: number | "unbounded" | undefined;
}
options) => {
const const keys: (string | symbol)[]keys = Reflect.function Reflect.ownKeys(target: object): (string | symbol)[]Returns the string and symbol keys of the own properties of an object. The own properties of an object
are those that are defined directly on that object, and are not inherited from the object's prototype.
ownKeys(input: objectinput)
const const issues: Array<SchemaIssue.Issue>issues: interface Array<T>Array<import SchemaIssueSchemaIssue.type Issue =
| SchemaIssue.Leaf
| SchemaIssue.Filter
| SchemaIssue.Encoding
| SchemaIssue.Pointer
| SchemaIssue.Composite
| SchemaIssue.AnyOf
The root discriminated union of all validation error nodes.
When to use
Use when typing the error channel in Effect<A, Issue, R> results from
schema parsing, or when writing custom formatters or issue-tree walkers.
Details
Every node has a _tag field for pattern-matching. The union includes both
terminal
Leaf
types and composite types that wrap inner issues:
Filter
,
Encoding
,
Pointer
,
Composite
,
AnyOf
. All Issue instances have a toString() that delegates to
the default formatter, so String(issue) produces a human-readable message.
Issue> = []
for (const const key: string | symbolkey of const keys: (string | symbol)[]keys) {
const const issue: SchemaIssue.Issue | undefinedissue = const parser: (
input: unknown,
options: SchemaAST.ParseOptions
) => SchemaIssue.Issue | undefined
parser(const key: string | symbolkey, options: SchemaAST.ParseOptions(parameter) options: {
errors: "first" | "all" | undefined;
onExcessProperty: "ignore" | "error" | "preserve" | undefined;
propertyOrder: "none" | "original" | undefined;
disableChecks: boolean | undefined;
concurrency: number | "unbounded" | undefined;
}
options)
if (const issue: SchemaIssue.Issue | undefinedissue !== var undefinedundefined) {
const issues: Array<SchemaIssue.Issue>issues.Array<Issue>.push(...items: SchemaIssue.Issue[]): numberAppends new elements to the end of an array, and returns the new length of the array.
push(new import SchemaIssueSchemaIssue.constructor Pointer(path: ReadonlyArray<PropertyKey>, issue: SchemaIssue.Issue): SchemaIssue.PointerWraps an inner
Issue
with a property-key path, indicating where in
a nested structure the error occurred.
When to use
Use when you need to walk the issue tree to accumulate path segments for error
reporting.
Details
path is an array of property keys (strings, numbers, or symbols).
- Has no
actual value —
getActual
returns Option.none().
- Formatters concatenate nested
Pointer paths into a single path like
["a"]["b"][0].
Pointer([const key: string | symbolkey], const issue: SchemaIssue.Issueissue))
if (options: SchemaAST.ParseOptions(parameter) options: {
errors: "first" | "all" | undefined;
onExcessProperty: "ignore" | "error" | "preserve" | undefined;
propertyOrder: "none" | "original" | undefined;
disableChecks: boolean | undefined;
concurrency: number | "unbounded" | undefined;
}
options.ParseOptions.errors?: "first" | "all" | undefinedControls how many parsing errors are reported.
Details
The default, "first", stops at the first error. Set the option to "all"
to collect every parsing error, which can help with debugging or with
presenting more complete error messages to a user.
errors === "first") break
}
}
if (import ArrArr.isArrayNonEmpty(const issues: Array<SchemaIssue.Issue>issues)) {
return new import SchemaIssueSchemaIssue.constructor Composite(ast: SchemaAST.AST, actual: StandardJSONSchemaV1<unknown>, issues: readonly [SchemaIssue.Issue, ...Array<SchemaIssue.Issue>]): SchemaIssue.CompositeRepresents a schema issue that groups multiple child issues under a single schema node.
When to use
Use when you need to walk the issue tree for struct/tuple schemas that collect
all field errors rather than failing on the first.
Details
issues is a non-empty readonly array (at least one child).
actual is Option.some(value) when the input was present, or
Option.none() when absent.
- Formatters flatten
Composite by recursing into each child.
Composite(ast: SchemaAST.ASTast, import Option_Option_.some(input: objectinput), const issues: Array<SchemaIssue.Issue>const issues: {
0: SchemaIssue.Issue;
length: number;
toString: () => string;
toLocaleString: { (): string; (locales: string | string[], options?: Intl.NumberFormatOptions & Intl.DateTimeFormatOptions): string };
pop: () => SchemaIssue.Issue | undefined;
push: (...items: Array<SchemaIssue.Issue>) => number;
concat: { (...items: Array<ConcatArray<SchemaIssue.Issue>>): Array<SchemaIssue.Issue>; (...items: Array<SchemaIssue.Issue | ConcatArray<SchemaIssue.Issue>>): Array<SchemaIssue.Issue> };
join: (separator?: string) => string;
reverse: () => Array<SchemaIssue.Issue>;
shift: () => SchemaIssue.Issue | undefined;
slice: (start?: number, end?: number) => Array<SchemaIssue.Issue>;
sort: (compareFn?: ((a: SchemaIssue.Issue, b: SchemaIssue.Issue) => number) | undefined) => [SchemaIssue.Issue, ...SchemaIssue.Issue[]];
splice: { (start: number, deleteCount?: number): Array<SchemaIssue.Issue>; (start: number, deleteCount: number, ...items: Array<SchemaIssue.Issue>): Array<SchemaIssue.Issue> };
unshift: (...items: Array<SchemaIssue.Issue>) => number;
indexOf: (searchElement: SchemaIssue.Issue, fromIndex?: number) => number;
lastIndexOf: (searchElement: SchemaIssue.Issue, fromIndex?: number) => number;
every: { (predicate: (value: SchemaIssue.Issue, index: number, array: Array<SchemaIssue.Issue>) => value is S, thisArg?: any): this is S[]; (predicate: (value: SchemaIssue.Issue, index: number, array: Array<SchemaIssue.Issue>) => unknown, thisArg…;
some: (predicate: (value: SchemaIssue.Issue, index: number, array: Array<SchemaIssue.Issue>) => unknown, thisArg?: any) => boolean;
forEach: (callbackfn: (value: SchemaIssue.Issue, index: number, array: Array<SchemaIssue.Issue>) => void, thisArg?: any) => void;
map: (callbackfn: (value: SchemaIssue.Issue, index: number, array: Array<SchemaIssue.Issue>) => U, thisArg?: any) => Array<U>;
filter: { (predicate: (value: SchemaIssue.Issue, index: number, array: Array<SchemaIssue.Issue>) => value is S, thisArg?: any): Array<S>; (predicate: (value: SchemaIssue.Issue, index: number, array: Array<SchemaIssue.Issue>) => unknown, thisArg?: …;
reduce: { (callbackfn: (previousValue: SchemaIssue.Issue, currentValue: SchemaIssue.Issue, currentIndex: number, array: Array<SchemaIssue.Issue>) => SchemaIssue.Issue): SchemaIssue.Issue; (callbackfn: (previousValue: SchemaIssue.Issue, currentValu…;
reduceRight: { (callbackfn: (previousValue: SchemaIssue.Issue, currentValue: SchemaIssue.Issue, currentIndex: number, array: Array<SchemaIssue.Issue>) => SchemaIssue.Issue): SchemaIssue.Issue; (callbackfn: (previousValue: SchemaIssue.Issue, currentValu…;
find: { (predicate: (value: SchemaIssue.Issue, index: number, obj: Array<SchemaIssue.Issue>) => value is S, thisArg?: any): S | undefined; (predicate: (value: SchemaIssue.Issue, index: number, obj: Array<SchemaIssue.Issue>) => unknown, thisArg?:…;
findIndex: (predicate: (value: SchemaIssue.Issue, index: number, obj: Array<SchemaIssue.Issue>) => unknown, thisArg?: any) => number;
fill: (value: SchemaIssue.Issue, start?: number, end?: number) => [SchemaIssue.Issue, ...SchemaIssue.Issue[]];
copyWithin: (target: number, start: number, end?: number) => [SchemaIssue.Issue, ...SchemaIssue.Issue[]];
entries: () => ArrayIterator<[number, SchemaIssue.Issue]>;
keys: () => ArrayIterator<number>;
values: () => ArrayIterator<SchemaIssue.Issue>;
includes: (searchElement: SchemaIssue.Issue, fromIndex?: number) => boolean;
flatMap: (callback: (this: This, value: SchemaIssue.Issue, index: number, array: Array<SchemaIssue.Issue>) => U | ReadonlyArray<U>, thisArg?: This | undefined) => Array<U>;
flat: (this: A, depth?: D | undefined) => Array<FlatArray<A, D>>;
at: (index: number) => SchemaIssue.Issue | undefined;
findLast: { (predicate: (value: SchemaIssue.Issue, index: number, array: Array<SchemaIssue.Issue>) => value is S, thisArg?: any): S | undefined; (predicate: (value: SchemaIssue.Issue, index: number, array: Array<SchemaIssue.Issue>) => unknown, thisA…;
findLastIndex: (predicate: (value: SchemaIssue.Issue, index: number, array: Array<SchemaIssue.Issue>) => unknown, thisArg?: any) => number;
toReversed: () => Array<SchemaIssue.Issue>;
toSorted: (compareFn?: ((a: SchemaIssue.Issue, b: SchemaIssue.Issue) => number) | undefined) => Array<SchemaIssue.Issue>;
toSpliced: { (start: number, deleteCount: number, ...items: Array<SchemaIssue.Issue>): Array<SchemaIssue.Issue>; (start: number, deleteCount?: number): Array<SchemaIssue.Issue> };
with: (index: number, value: SchemaIssue.Issue) => Array<SchemaIssue.Issue>;
}
issues)
}
return true
},
{
Annotations.Augment.expected?: string | undefinedHuman-readable description of what a value is expected to satisfy.
Details
For filter and refinement failures, the default formatter uses
message first, then expected, and finally falls back to <filter>.
Use this to name a failed filter in the default message:
Expected <expected>, got <actual>.
expected: "an object with property names matching the schema",
Annotations.Filter.meta?: Annotations.Meta | undefined(property) Annotations.Filter.meta?: {
_tag: 'isPropertyNames';
propertyNames: SchemaAST.AST;
}
Optional metadata used to identify or extend the filter with custom data.
meta: {
_tag: "isPropertyNames"_tag: "isPropertyNames",
propertyNames: SchemaAST.ASTpropertyNames: const propertyNames: toEncoded<Constraint>const propertyNames: {
Type: S["Encoded"];
Encoded: S["Encoded"];
DecodingServices: never;
EncodingServices: never;
Iso: S["Encoded"];
schema: S;
Rebuild: Rebuild;
ast: Ast;
annotate: (annotations: Annotations.Bottom<unknown, ReadonlyArray<Constraint>>) => toEncoded<Constraint>;
annotateKey: (annotations: Annotations.Key<unknown>) => toEncoded<Constraint>;
check: (checks_0: SchemaAST.Check<unknown>, ...checks: Array<SchemaAST.Check<unknown>>) => toEncoded<Constraint>;
rebuild: (ast: SchemaAST.AST) => toEncoded<Constraint>;
make: (input: unknown, options?: MakeOptions) => unknown;
makeOption: (input: unknown, options?: MakeOptions) => Option_.Option<unknown>;
makeEffect: (input: unknown, options?: MakeOptions) => Effect.Effect<unknown, SchemaError, never>;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
propertyNames.Bottom<unknown, unknown, unknown, unknown, AST, toEncoded<Constraint>, unknown, unknown, readonly Constraint[], unknown, Mutability, Optionality, ConstructorDefault, Mutability, Optionality>["ast"]: SchemaAST.ASTast
},
[import SchemaASTSchemaAST.const STRUCTURAL_ANNOTATION_KEY: "~structural"STRUCTURAL_ANNOTATION_KEY]: true,
...annotations: Annotations.Filter | undefinedannotations
}
)
}