Schema to Standard Schema
Schema.toStandardSchemaV1 exposes an Effect schema through the Standard Schema V1 interface. The resulting object can be passed to libraries that support the standard while retaining the original Effect schema APIs.
Example (Generating a Standard Schema V1)
import { Schema } from "effect"
const schema = Schema.Struct({ name: Schema.String,})
// Convert an Effect schema into a Standard Schema V1 objectconst standardSchema = Schema.toStandardSchemaV1(schema)
standardSchema["~standard"].vendor // => "effect"Sync vs Async Validation
The Standard Schema validate method first attempts to decode synchronously. If decoding encounters an asynchronous transformation or check, it returns a Promise instead.
Example (Handling Synchronous and Asynchronous Validation)
import { Effect, Schema, SchemaGetter } from "effect"
// Utility function to display sync and async resultsconst print = <T>(t: T) => t instanceof Promise ? t.then((x) => console.log("Promise", JSON.stringify(x, null, 2))) : console.log("Value", JSON.stringify(t, null, 2))
// Define a synchronous schemaconst sync = Schema.Struct({ name: Schema.String,})
// Generate a Standard Schema V1 objectconst syncStandardSchema = Schema.toStandardSchemaV1(sync)
// Validate synchronouslyprint(syncStandardSchema["~standard"].validate({ name: null }))syncStandardSchema["~standard"].validate({ name: null }) // => { issues: [{ path: ["name"], message: "Expected string" }] }/*Output:{ "issues": [ { "path": [ "name" ], "message": "Expected string" } ]}*/
// Define an asynchronous schema with a transformationconst async = sync.pipe( Schema.decodeTo( Schema.Struct({ name: Schema.NonEmptyString, }), { // Simulate an asynchronous validation delay decode: SchemaGetter.transformOrFail((x) => Effect.sleep("100 millis").pipe(Effect.as(x)), ), encode: SchemaGetter.passthrough(), }, ),)
// Generate a Standard Schema V1 objectconst asyncStandardSchema = Schema.toStandardSchemaV1(async)
// Validate asynchronouslyprint(asyncStandardSchema["~standard"].validate({ name: "" }))await asyncStandardSchema["~standard"].validate({ name: "" }) // => { issues: [{ path: ["name"], message: "Expected a value with a length of at least 1" }] }/*Output:Promise { "issues": [ { "path": [ "name" ], "message": "Expected a value with a length of at least 1" } ]}*/Defects
If an unexpected defect occurs during validation, it is reported as a single issue without a path. This ensures that unexpected errors do not disrupt schema validation but are still captured and reported.
Example (Handling Defects)
import { Effect, Schema, SchemaGetter } from "effect"
// Define a schema with a defect in the decode functionconst defect = Schema.String.pipe( Schema.decodeTo(Schema.String, { // Simulate an internal failure decode: SchemaGetter.transformOrFail(() => Effect.die("Boom!")), encode: SchemaGetter.passthrough(), }),)
// Generate a Standard Schema V1 objectconst defectStandardSchema = Schema.toStandardSchemaV1(defect)
// Validate input, triggering a defectconsole.log(defectStandardSchema["~standard"].validate("a"))/*Output:{ issues: [ { message: 'Error: Boom!' } ] }*/Standard Schema failures use the same formatter described in Error Formatters. Pass leafHook, checkHook, or parseOptions to Schema.toStandardSchemaV1 to customize its output.