Skip to content

@pcvl/schema / Schema

Interface: Schema<Input, Output> ​

Defined in: schemas/schema.ts:35

What every schema in this library is: something that validates a value. A field of an object schema, an element of an array schema and a member of a union are each typed as one, so any schema fits there. It is also what .transform() and pvl.compile() hand back, since no modifier can be chained onto either: chain constraints, .optional() and .refine() first.

Input is what a value must look like going in; Output is what a successful .validate() hands back, which differs from Input once a .transform() is attached.

Example ​

ts
import { pvl, type Schema } from '@pcvl/schema';

const length: Schema<string, number> = pvl.string().transform((value) => value.length);

length.validate('abc'); // { value: 3 }
pvl.object({ name: length }).validate({ name: 'Ada' }); // { value: { name: 3 } }

Type Parameters ​

Input ​

Input = unknown

Output ​

Output = Input

Methods ​

standalone() ​

ts
standalone(): Schema<Input, Output> & StandaloneMarker;

Defined in: schemas/schema.ts:113

Marks this schema as a Standalone Key: as a field of pvl.object(), it is kept in that object's shape, so it can be validated on its own, and once the object is compiled, @pcvl/compiler gives it a compiled validator of its own. Validation is unchanged.

The schema comes back as the same type it went in as, marked, so the chain goes on: modifiers can follow it, and an object keeps its shape and an array its element. It is valid on any schema, a field or not, and calling it again changes nothing.

Returns ​

Schema<Input, Output> & StandaloneMarker

Example ​

ts
import { pvl } from '@pcvl/schema';

const user = pvl.object({
  email: pvl.string().standalone().min(3),
  age: pvl.number().int(),
});

user.shape.email.validate('a@b.c'); // { value: 'a@b.c' }
// user.shape.age — a compile error: `age` isn't a Standalone Key

validate() ​

ts
validate(value): Result<Output>;

Defined in: schemas/schema.ts:74

Checks a value against this schema and returns a Result synchronously. It never throws for an invalid value — a rejection comes back as issues, so the two branches are handled the same way every time.

Parameters ​

value ​

unknown

Returns ​

Result<Output>

Example ​

ts
import { pvl } from '@pcvl/schema';

const result = pvl.number().int().validate(1.5);
if (result.issues) {
  console.log(result.issues[0]?.message); // 'Number must be an integer'
} else {
  console.log(result.value);
}