Skip to content

Validation

Validation: object

Defined in: Core/Validation.ts:35

ap: <E, A>(arg) => <B>(data) => Validation<E, B>

Applies a function wrapped in a Validation to a value wrapped in a Validation. Accumulates errors from both sides.

E

A

Validation<E, A>

<B>(data) => Validation<E, B>

const add = (a: number) => (b: number) => a + b;
pipe(
  Validation.make.passed(add),
  Validation.ap(Validation.make.passed(5)),
  Validation.ap(Validation.make.passed(3))
); // Passed(8)

pipe(
  Validation.make.passed(add),
  Validation.ap(Validation.make.failed<string>("bad a")),
  Validation.ap(Validation.make.failed<string>("bad b"))
); // Failed(["bad a", "bad b"])

apCustom: <E1, E2, E3>(concat) => <A>(arg) => <B>(data) => Validation<E3, B>

Applies a function wrapped in a Validation to a value wrapped in a Validation, using a custom error concatenator function when both sides fail.

E1

E2

E3

(e1, e2) => NonEmptyArr<E3>

<A>(arg) => <B>(data) => Validation<E3, B>

const concat = (e1: NonEmptyArr<string>, e2: NonEmptyArr<string>): NonEmptyArr<string> =>
  [...e1, ...e2];
pipe(fnVal, Validation.apCustom(concat)(argVal));

fold: <E, A, B>(onFailed, onPassed) => (data) => B

Extracts the value from a Validation by providing handlers for both cases.

E

A

B

(errors) => B

(a) => B

(data) => B

pipe(
  Validation.make.passed(42),
  Validation.fold(
    errors => `Errors: ${errors.join(", ")}`,
    value => `Value: ${value}`
  )
);

from: object

Maybe: <E>(onNone) => <A>(maybe) => Validation<E, A>

Creates a Validation from a Maybe. If the Maybe is None, returns Failed with the error from onNone. Otherwise, returns Passed.

E

() => E

<A>(maybe) => Validation<E, A>

pipe(Maybe.make.none(), Validation.from.Maybe(() => "is none")); // Failed(["is none"])
pipe(Maybe.make.some(42), Validation.from.Maybe(() => "is none")); // Passed(42)

nullable: <E>(onNull) => <A>(value) => Validation<E, A>

Creates a Validation from a nullable value. If the value is null or undefined, returns Failed with the error from onNull. Otherwise, returns Passed.

E

() => E

<A>(value) => Validation<E, A>

pipe(null, Validation.from.nullable(() => "is null")); // Failed(["is null"])
pipe(42, Validation.from.nullable(() => "is null"));   // Passed(42)

Predicate: <E, A>(pred, onFalse) => (a) => Validation<E, A>

Creates a Validation from a predicate applied to a value. Returns Passed if the predicate passes, Failed from onFalse otherwise.

E

A

(a) => boolean

(a) => E

(a) => Validation<E, A>

const validateName = Validation.from.Predicate(
  (s: string) => s.length > 0,
  () => "Name is required"
);

validateName("Alice"); // Passed("Alice")
validateName("");      // Failed(["Name is required"])

Result: <E, A>(data) => Validation<E, A>

Converts a Result to a Validation. Ok becomes Passed; Err(e) becomes Failed([e]).

Useful when bridging from error-short-circuiting Result pipelines into error-accumulating Validation pipelines.

E

A

Result<E, A>

Validation<E, A>

Validation.from.Result(Result.make.ok(42));       // Passed(42)
Validation.from.Result(Result.make.err("bad"));   // Failed(["bad"])

getOrElse: <B>(defaultValue) => <E, A>(data) => B | A

Returns the success value or a default value if the Validation is failed. The default can be a different type, widening the result to A | B.

B

() => B

<E, A>(data) => B | A

pipe(Validation.make.passed(5), Validation.getOrElse(() => 0)); // 5
pipe(Validation.make.failed("oops"), Validation.getOrElse(() => 0)); // 0
pipe(Validation.make.failed("oops"), Validation.getOrElse(() => null)); // null — typed as number | null

is: object

failed: <E, A>(data) => data is Failed<E> = isFailed

Type guard that checks if a Validation is failed.

E

A

Validation<E, A>

data is Failed<E>

const v = Validation.make.failed("invalid");
if (Validation.is.failed(v)) {
  console.log(v.errors); // ["invalid"]
}

passed: <E, A>(data) => data is Passed<A> = isPassed

Type guard that checks if a Validation is passed.

E

A

Validation<E, A>

data is Passed<A>

const v = Validation.make.passed(42);
if (Validation.is.passed(v)) {
  console.log(v.value); // 42
}

make: object

failed: <E>(error) => Failed<E> = makeFailed

Creates a failed Validation from a single error.

E

E

Failed<E>

Validation.make.failed("Invalid input");

failedAll: <E>(errors) => Failed<E> = makeFailedAll

Creates a failed Validation from multiple errors.

E

NonEmptyArr<E>

Failed<E>

Validation.make.failedAll(["Invalid input"]);

passed: <E, A>(value) => Validation<E, A> = makePassed

Wraps a value in a passed Validation.

E

A

A

Validation<E, A>

Validation.make.passed(42); // Passed(42)

map: <A, B>(f) => <E>(data) => Validation<E, B>

Transforms the success value inside a Validation.

A

B

(a) => B

<E>(data) => Validation<E, B>

pipe(Validation.make.passed(5), Validation.map(n => n * 2)); // Passed(10)
pipe(Validation.make.failed("oops"), Validation.map(n => n * 2)); // Failed(["oops"])

mapError: <E, F, A>(f) => (data) => Validation<F, A>

Transforms the error list inside a Validation.

E

F

A

(e) => F

(data) => Validation<F, A>

pipe(Validation.make.failed("oops"), Validation.mapError(e => e.toUpperCase())); // Failed(["OOPS"])

match: <E, A, B>(cases) => (data) => B

Pattern matches on a Validation, returning the result of the matching case.

E

A

B

(errors) => B

(a) => B

(data) => B

pipe(
  validation,
  Validation.match({
    passed: value => `Got ${value}`,
    failed: errors => `Failed: ${errors.join(", ")}`
  })
);

product: <E, A, B>(first, second) => Validation<E, readonly [A, B]>

Combines two independent Validation instances into a tuple. If both are Passed, returns Passed with both values as a tuple. If either is Failed, accumulates errors from both sides.

E

A

B

Validation<E, A>

Validation<E, B>

Validation<E, readonly [A, B]>

Validation.product(
  Validation.make.passed("alice"),
  Validation.make.passed(30)
); // Passed(["alice", 30])

Validation.product(
  Validation.make.failed("Name required"),
  Validation.make.failed("Age must be >= 0")
); // Failed(["Name required", "Age must be >= 0"])

productAll: <E, A>(data) => Validation<E, readonly A[]>

Combines a non-empty list of Validation instances, accumulating all errors. If all are Passed, returns Passed with all values collected into an array. If any are Failed, returns Failed with all accumulated errors.

E

A

NonEmptyArr<Validation<E, A>>

Validation<E, readonly A[]>

Validation.productAll([
  validateName(name),
  validateEmail(email),
  validateAge(age)
]);
// Passed([name, email, age]) or Failed([...all errors])

recover: <E, B>(fallback) => <A>(data) => Validation<E, B | A>

Recovers from a Failed state by providing a fallback Validation. The fallback receives the accumulated error list so callers can inspect which errors occurred. The fallback can produce a different success type, widening the result to Validation<E, A | B>.

E

B

(errors) => Validation<E, B>

<A>(data) => Validation<E, B | A>

recoverUnless: <E, B>(isBlocked, fallback) => <A>(data) => Validation<E, B | A>

Recovers from a Failed state unless isBlocked returns true for any of the accumulated errors. The fallback can produce a different success type, widening the result to Validation<E, A | B>.

E

B

(e) => boolean

() => Validation<E, B>

<A>(data) => Validation<E, B | A>

pipe(
  Validation.make.failed("field-error"),
  Validation.recoverUnless(e => e === "fatal", () => Validation.make.passed(0))
); // Passed(0)

struct: <E, R>(fields) => Validation<E, R>

Combines a record of Validations into a single Validation of a record. Accumulates all failed branches’ errors.

E

R extends Record<string, any>

{ [K in string | number | symbol]: Validation<E, R[K]> }

Validation<E, R>

Validation.struct({
  name: Validation.make.passed("Alice"),
  age: Validation.make.passed(30)
}); // Passed({ name: "Alice", age: 30 })

Validation.struct({
  name: Validation.make.failed("Name required"),
  age: Validation.make.failed("Age must be >= 0")
}); // Failed(["Name required", "Age must be >= 0"])

tap: <E, A>(f) => (data) => Validation<E, A>

Executes a side effect on the success value without changing the Validation.

E

A

(a) => void

(data) => Validation<E, A>

pipe(
  Validation.make.passed(5),
  Validation.tap(n => console.log("Value:", n)),
  Validation.map(n => n * 2)
);

tapError: <E, A>(f) => (data) => Validation<E, A>

Executes a side effect on the accumulated errors without changing the Validation. Useful for logging or reporting validation failures.

E

A

(errors) => void

(data) => Validation<E, A>

pipe(
  Validation.make.failed("Name required"),
  Validation.tapError(errors => console.error("validation failed:", errors)),
  Validation.map(toUser)
);

to: object

Maybe: <E, A>(data) => Maybe<A>

Converts a Validation to a Maybe. Passed becomes Some; Failed becomes None (errors are discarded).

E

A

Validation<E, A>

Maybe<A>

Validation.to.Maybe(Validation.make.passed(42));       // Some(42)
Validation.to.Maybe(Validation.make.failed("bad"));  // None

Result: {<E1, E2, A>(combineErrors): (val) => Result<E2, A>; <E, A>(data): Result<NonEmptyArr<E>, A>; } = toResult

Converts a Validation to a Result. Passed becomes Ok. Direct call converts Failed to Err with accumulated error list NonEmptyArr<E>. Curried call converts Failed to Err with combined error E2 via combineErrors.

<E1, E2, A>(combineErrors): (val) => Result<E2, A>

E1

E2

A

(errors) => E2

(val) => Result<E2, A>

<E, A>(data): Result<NonEmptyArr<E>, A>

E

A

Validation<E, A>

Result<NonEmptyArr<E>, A>

Validation.to.Result(Validation.make.passed(42));        // Ok(42)
Validation.to.Result(Validation.make.failed("oops"));  // Err(["oops"])
pipe(Validation.make.failed("oops"), Validation.to.Result(errors => errors.join(", "))); // Err("oops")

tryCatch: <E, A>(f, options) => Validation<E, A>

Creates a Validation from a synchronous thunk that may throw. Catches any errors and transforms them using the onError function into a Failed validation.

E

A

() => A

(e) => E

Validation<E, A>

const result = Validation.tryCatch(
  () => JSON.parse(rawString),
  { onError: (e) => `Parse error: ${e}` }
);