Aborting Early

Avatar of Hemanta SundarayHemanta Sundaray

Sometimes a single field has multiple checks. A password field, for example, might first check that it is not empty, and then check that it is at least 8 characters long. If the password is empty, there is no point telling the user it must be at least 8 characters. They haven’t provided a password at all. The only error that matters is: “password is required.”

.abort() solves this. You call it on a check, and if that check fails, Schema stops running any further checks on that same value, even when { errors: "all" } is active.

schema.ts
import { Schema } from "effect";
const User = Schema.Struct({
email: Schema.String,
password: Schema.String.check(
Schema.isMinLength(1).abort(), // If empty, stop here
Schema.isMinLength(8), // Must be at least 8 characters
Schema.isPattern(/\d/), // Must contain at least one digit
),
});
const result = Schema.decodeUnknownExit(User)(
{ email: "alice@example.com", password: "" },
{ errors: "all" },
);
console.log(String(result));

Output:

Terminal
Failure(Cause([Fail(SchemaError(Expected a value with a length of at least 1, got ""
at ["password"]))]))

The password "hi" is only 2 characters, so it fails the isMinLength(8) check. Because that check has .abort(), Schema does not bother checking whether the password contains a digit. Only the length error is reported.

Note

.abort() only affects the chain of checks on a single value. It doesn’t stop Schema from checking other fields in a struct. If you have { errors: "all" } and a struct with two fields, .abort() on field A’s checks won’t prevent field B’s checks from running.

Sign in to save progress

Stay in the loop

Get notified when new chapters are added and when this course is complete.