Runtime type validation and transformation system with Schema for parsing, encoding, and validating data with comprehensive error reporting and type safety.
interface Schema<in in out A, in in out I = A, out R = never> extends Pipeable {}
declare namespace Schema {
/**
* Primitive schemas
*/
const String: Schema<string>;
const Number: Schema<number>;
const Boolean: Schema<boolean>;
const Date: Schema<Date>;
/**
* Collection schemas
*/
function Array<A, I, R>(item: Schema<A, I, R>): Schema<ReadonlyArray<A>, ReadonlyArray<I>, R>;
function NonEmptyArray<A, I, R>(item: Schema<A, I, R>): Schema<NonEmptyReadonlyArray<A>, NonEmptyReadonlyArray<I>, R>;
/**
* Object schemas
*/
function Struct<Fields>(fields: Fields): Schema<{ readonly [K in keyof Fields]: Schema.Type<Fields[K]> }>;
function Record<K extends PropertyKey, A, I, R>(key: Schema<K>, value: Schema<A, I, R>): Schema<{ readonly [P in K]: A }, { readonly [P in K]: I }, R>;
/**
* Union and optional schemas
*/
function Union<Members extends readonly [Schema<any, any, any>, ...Array<Schema<any, any, any>>]>(...members: Members): Schema<Schema.Type<Members[number]>>;
function Optional<A, I, R>(schema: Schema<A, I, R>): Schema<A | undefined, I | undefined, R>;
function Nullable<A, I, R>(schema: Schema<A, I, R>): Schema<A | null, I | null, R>;
/**
* Parsing and validation
*/
function decode<A, I, R>(schema: Schema<A, I, R>): (u: unknown) => Effect<A, ParseResult.ParseError, R>;
function encode<A, I, R>(schema: Schema<A, I, R>): (a: A) => Effect<I, ParseResult.ParseError, R>;
function parse<A, I, R>(schema: Schema<A, I, R>): (u: unknown) => Effect<A, ParseResult.ParseError, R>;
/**
* Type utilities
*/
type Type<S> = S extends Schema<infer A, any, any> ? A : never;
type Encoded<S> = S extends Schema<any, infer I, any> ? I : never;
type Context<S> = S extends Schema<any, any, infer R> ? R : never;
}Usage Examples:
import { Schema, Effect, pipe } from "effect";
// Basic schemas
const UserSchema = Schema.Struct({
id: Schema.Number,
name: Schema.String,
email: Schema.String,
age: Schema.Optional(Schema.Number),
active: Schema.Boolean
});
type User = Schema.Type<typeof UserSchema>;
// Array schema
const UsersSchema = Schema.Array(UserSchema);
// Validation
const parseUser = Schema.decode(UserSchema);
const result = await Effect.runPromise(
parseUser({
id: 1,
name: "John Doe",
email: "john@example.com",
active: true
})
);
// Complex validation
const ApiResponseSchema = Schema.Struct({
success: Schema.Boolean,
data: Schema.Union(UserSchema, Schema.Array(UserSchema)),
errors: Schema.Optional(Schema.Array(Schema.String))
});
// Custom transformations
const DateFromString = Schema.transformOrFail(
Schema.String,
Schema.Date,
(s, _, ast) => {
const date = new Date(s);
return isNaN(date.getTime())
? ParseResult.fail(ParseResult.type(ast, s))
: ParseResult.succeed(date);
},
(date) => ParseResult.succeed(date.toISOString())
);declare namespace ParseResult {
interface ParseError {
readonly _tag: "ParseError";
readonly error: ParseIssue;
}
interface ParseIssue {
readonly path: ReadonlyArray<PropertyKey>;
readonly message: string;
readonly issues?: ReadonlyArray<ParseIssue>;
}
}