Class: Validation

Validation

The Validation type is intended for validating values and aggregating failures. It is a disjunction similar to Either. The key difference of the Validation type is the focus on failure aggregation as opposed to failing once and ignoring all other failures. Much like Either, Validation is right-biased.

new Validation(value){Validation}

Name Type Description
value * Value to wrap.
Returns:
Type Description
Validation Validation wrapped value.
Examples

Via new

const v1 = new Success(value);
const v2 = new Failure(message);

Via function

const v3 = Success.from(value);
const v4 = Failure.from(message);

Via validation function

const isEmpty = require("lodash/fp/isEmpty");
const isString = require("lodash/fp/isString");
const Validation = require("lodash-fantasy/data/Validation");

function validateStringPresence(value) {
  return isString(value) && !isEmpty(value) ?
    Validation.Success.from(value) :
    Validation.Failure.from("value should be a non-empty string");
}

module.exports = validateStringPresence;

Via abstract validation rule

const Validation = require("lodash-fantasy/data/Validation");

module.exports = (condition, value, message) => condition(value) ?
  Validation.Success.from(value) :
  Validation.Failure.from(message(value)); // Pass value into the message for possible reference

Members

staticValidation.all

Returns a Validation that resolves all of the validations in the collection into a single validation. Unlike Promise, Validation.all aggregates all of the failures into a single instance of Validation. However, like Promise, Validation.all collects all of the values for successes when all items in the collection are a Success.
Example
const v1 = validationPropertyAIn(context1);
// => Success(context1)

const v2 = validationPropertyBIn(context2);
// => Success(context2)

const v3 = validationPropertyCIn(context3);
// => Failure("A failure.")

const v4 = validationPropertyDIn(context4);
// => Failure("B failure.")

Validation.all([v1, v2]);
// => Success([context1, context2])

Validation.all([v1, v2, v3]);
// => Failure(["A failure"])

Validation.all([v1, v2, v3, v4]);
// => Failure(["A failure", "B failure"])

staticValidation.any

Returns the first Success in the collection or a single Failure for all failures.
Example
const v1 = validationPropertyAIn(context1);
// => Success(context1)

const v2 = validationPropertyBIn(context2);
// => Success(context2)

const v3 = validationPropertyCIn(context3);
// => Failure("A failure.")

const v4 = validationPropertyDIn(context4);
// => Failure("B failure.")

Validation.any([v1, v2]);
// => Success(context1)

Validation.any([v1, v2, v3]);
// => Failure(["A failure"])

Validation.any([v1, v2, v3, v4]);
// => Failure(["A failure", "B failure"])

staticValidation.concat

Concatenates two Validation instances together.
Example

Concatenating distinct validations

const validations = [
  validatePersonName(person), // => Success(person)
  validatePersonBirthdate(person), // => Success(person)
  validatePersonAddress(person), // => Failure([error1])
  validatePersonEmail(person) // => Failure([error2])
];

Validation.reduce(Validation.concat, Success.empty(), validations);
// => Failure([error1, error2])

staticValidation.each

Iterates over a collection of validations and invokes the iteratee for each Validation. The iteratee is invoked with one argument: (validation). Iteratee functions may exit iteration early by explicitly returning a Failure.
Example
const validations = [
  validatePerson(person1), // => Success(person1)
  validatePerson(person2), // => Success(person2)
  validatePerson(person3), // => Failure([error1, error2])
  validatePerson(person4) // => Failure([error2])
];

Validation.each(validation => validation.orElse(flow(join(", "), console.error)), validations);
// => Logs 'error1, error2' then 'error2'
//
// => validations

staticValidation.empty

Creates an empty Success.
Example
const v1 = Validation.empty();
// => Success()

staticValidation.equals

Determines whether or not the other is equal in value to the current (this). This is not a reference check.
Examples

Reflexivity

Validation.equals(v1, v1) === true;
// => true

Symmetry

Validation(v1, v2) === Validation.equals(v2, v1);
// => true

Transitivity

(Validation.equals(v1, v2) === Validation.equals(v2, v3)) && Validation.equals(v1, v3)
// => true

staticValidation.Failure

Properties:
Name Type Description
Failure Failure Validation failure.

staticValidation.filter

Iterates over a collection of validations, returning an array of all validations the predicate for which returns truthy. The predicate is invoked with one argument: (validation).
Example

Filter and log failures

const validations = [
  validatePerson(person1), // => Success(person1)
  validatePerson(person2), // => Success(person2)
  validatePerson(person3), // => Failure([error1, error2])
  validatePerson(person4) // => Failure([error2])
];

// Log failures, return successes.
Validation.filter(validation => validation.orElse(flow(join(", "), console.error)).isSuccess(), validations);
// => Logs 'error1, error2' then 'error2'
//
// => [Success(person1), Success(person2)]

staticValidation.from

Creates a new Validation from a value. If the value is already a Validation instance, the value is returned unchanged. Otherwise, a new Success is created with the value.

staticValidation.isFailure

Determines whether or not the value is a Failure.
Example
isFailure();
// => false

isFailure(null);
// => false

isFailure(Success.from(0));
// => false

isFailure(Failure.from("Error"));
// => true

staticValidation.isSuccess

Determines whether or not the value is a Success.
Example
isSuccess();
// => false

isSuccess(null);
// => false

isSuccess(Success.from(0));
// => true

isSuccess(Failure.from("Error"));
// => false

staticValidation.isValidation

Determines whether or not the value is a Validation.
Example
isValidation();
// => false

isValidation(null);
// => false

isValidation(Success.from(0));
// => true

isValidation(Failure.from("Error"));
// => true

staticValidation.map

Creates an array of values by running each Validation in collection through the iteratee. The iteratee is invoked with one argument: (validation).
Example

Mapping all validations to promises

const validations = [
  validatePrice(2.10), // => Success(price1)
  validatePrice(2.25), // => Success(price2)
  validatePrice("2.50"), // => Failure([error1])
  validatePrice("Three dollars") // => Failure([error1])
];

Validation.map(Validation.toPromise, validations);
// => [Promise.resolve(price1), Promise.resolve(price2), Promise.reject([error1]), Promise.reject([error2])]

staticValidation.mapIn

Creates an array of values by invoking Validation#map with the iteratee for each Validation in the collection. The iteratee is invoked with one argument: (value).
Example

Mapping each Validation's value

const validations = [
  validatePrice(2.10), // => Success(price1)
  validatePrice(2.25), // => Success(price2)
  validatePrice("2.50"), // => Failure([error1])
  validatePrice("Three dollars") // => Failure([error1])
];

Validation.mapIn(Math.floor, validations);
// => [Success(2), Success(2), Failure([error1]), Failure([error2])]

staticValidation.of

Wraps the value in a Success. No parts of value are checked.
Example
Validation.of();
// => Success()

Validation.of(true);
// => Success(true)

Validation.of(Success.from(value));
// => Success(Success(value))

Validation.of(Failure.from("Error message"));
// => Success(Failure(["Error message"]))

staticValidation.reduce

Reduces collection to a value which is the accumulated result of running each validation in the validations collection through the iteratee, where each successive invocation is supplied the return value of the previous. The iteratee is invoked with two arguments: (accumulator, value).
Example
const validations = [
  validatePersonName(person), // => Success(person)
  validatePersonBirthdate(person), // => Success(person)
  validatePersonAddress(person), // => Failure([error1])
  validatePersonEmail(person) // => Failure([error2])
];

Validation.reduce(Validation.concat, Success.empty(), validations);
// => Failure([error1, error2])

staticValidation.Success

Properties:
Name Type Description
Success Success Validation success.

staticValidation.toEither

Converts a Validation to an Either. Success becomes a Right and Failure becomes Left.
Examples

Success to Resolved

Validation.toEither(Either, Success.from(value));
// => Either.Right(value);

Failure to Rejected

Validation.toEither(Either, Failure.from(error));
// => Either.Left([error]);

staticValidation.toMaybe

Converts a Validation to an Maybe. Success becomes a Just and Failure becomes Nothing.
Examples

Success to Resolved

Validation.toMaybe(Maybe, Success.from(value));
// => Maybe.Just(value);

Failure to Rejected

Validation.toMaybe(Maybe, Failure.from(error));
// => Maybe.Nothing();

staticValidation.toPromise

Converts a validation to a Promise using the provided Promise implementation.
Example

Convert with bluebird's implementation of Promise

const toBluebird = Validation.toPromise(require("bluebird"));

toBluebird(Success.from(value));
// => Promise.resolve(value);

toBluebird(Failure.from(error));
// => Promise.reject([error]);

staticValidation.try

Tries to invoke a supplier. The result of the supplier is returned in a Success. If an exception is thrown, the error is returned in a Failure. The function takes no arguments.
Example
Validation.try(normalFunction);
// => Success(returnValue)

Validation.try(throwableFunction);
// => Failure([error])

Methods

abstractap(other){Validation}

Applies the function contained in the instance of a Success to the value contained in the provided Success, producing a Success containing the result. If the instance is a Failure, the result is the Failure instance. If the instance is a Success and the provided validation is Failure, the result is the provided Failure.
Name Type Description
other Validation Value to apply to the function wrapped in the Success.
Returns:
Type Description
Validation Success wrapped applied function or Failure.
Example

Success#ap

const createPerson = curryN(4, Person.create); // Person.create(name, birthdate, address, email)

Success.from(createPerson) // => Success(createPerson)
  .ap(validate(name)) // => Success(name)
  .ap(validate(birthdate)) // => Success(birthdate)
  .ap(validate(address)) // => Success(address)
  .ap(validate(email)) // => Success(email)
  .ifSuccess(console.log) // => Log Person.create() response
  .orElse(each(console.error)) // => Logs first error since #ap short circuits after the first Failure

abstractbimap(failureMap, successMap){Validation}

Transforms a Validation by applying the first function to the contained value for a Failure or the second function for a Success. The result of each map is wrapped in the corresponding type.
Name Type Description
failureMap function Map to apply to the Failure.
successMap function Map to apply to the Success.
Returns:
Type Description
Validation Validation wrapped value mapped with the corresponding mapping function.
Example
validateRequest(request)
  .bimap(toBadRequestResponse, PersonModel.create)
  // ... other actions in workflow

abstractchain(method){Validation}

Applies the provided function to the value contained for a Success. The function should return the value wrapped in a Validation. If the instance is a Failure, the function is ignored and then instance is returned unchanged.
Name Type Description
method Chain.<Validation> The function to invoke with the value.
Returns:
Type Description
Validation Validation wrapped value returned by the provided method.
Example

Success#chain

const person = { ... };
const validateResponse = response => HttpStatus.isSuccess(response.statusCode) ?
  Success(response) :
  Failure(response.statusMessage);

const createPerson = flow(Person.create, validateResponse); // Expects instance of Person

const validations = [
  validatePersonName(person), // => Success(person)
  validatePersonBirthdate(person), // => Success(person)
  validatePersonAddress(person), // => Failure([error1])
  validatePersonEmail(person) // => Failure([error2])
];

Validation.reduce(Validation.concat, Success.empty(), validations) // => Validation
  .chain(createPerson) // => Validation
  .ifSuccess(doSomethingWithResponse)
  .orElse(each(console.error)); // Log all errors

abstractconcat(other){Validation}

Concatenates another Validation instance with the current instance.
Name Type Description
other Validation Other Validation to concatenation.
Returns:
Type Description
Validation Concatenated validations.
Examples

Empty Success with Empty Success

Success.empty().concat(Success.empty());
// => Success.empty()

Empty Success with Success

Success.empty().concat(Success.from(value));
// => Success(value)

Success with Empty Success

Success.from(value).concat(Success.empty());
// => Success(value)

Success1 with Success2

Success.from(value1).concat(Success.from(value2));
// => Success(value1)

Any Success with Failure

anySuccess.concat(Failure.from(error));
// => Failure([error])

Empty Failure with Any Success

Failure.from().concat(anySuccess);
// => Failure([])

Failure with Any Success

Failure.from(error).concat(Success);
// => Failure([error])

Empty Failure with Empty Failure

Failure.from().concat(Failure.from());
// => Failure([])

Empty Failure with Failure

Failure.from().concat(Failure.from(error));
// => Failure([error])

Failure with Failure

Failure.from(error1).concat(Failure.from(error2));
// => Failure([error1, error2])

equals(other){Boolean}

Determines whether or not the other is equal in value to the current (this). This is not a reference check.
Name Type Description
other * Other value to check.
Returns:
Type Description
Boolean true if the two validations are equal; false if not equal.
Examples

Reflexivity

v1.equals(v1) === true;
// => true

Symmetry

v1.equals(v2) === v2.equals(v1);
// => true

Transitivity

(v1.equals(v2) === v2.equals(v3)) && v1.equals(v3)
// => true
Extends the validation. This is used for workflow continuation where the context has shifted.
Type Description
Extend.<Validation> method - The function to invoke with the value.
Returns:
Type Description
Validation
Example

Workflow continuation

// Workflow from makeRequest.js
const makeRequest = requestOptions => requestAsPromise(requestOptions)
  .then(Success.from)
  .catch(Failure.from);

// Workflow from savePerson.js
const savePerson = curry((requestOptions, validatedPerson) => {
  return validatedPerson
    .map(Person.from)
    .map(person => set("body", person, requestOptions))
    .map(makeRequest);
});

// Workflow from processResponse.js
const processResponse = validatedResponse => validatedResponse
  .ifFailure(console.error)
  .ifSuccess(console.log);

validatePerson(person)
  .extend(savePerson({ method: "POST" }))
  .extend(processResponse);

abstractifFailure(method){Validation}

Applies the provided function to the value contain for a Failure. Any return value from the function is ignored. If the instance is a Success, the function is ignored and the instance is returned.
Name Type Description
method Consumer The function to invoke with the value.
Returns:
Type Description
Validation Current instance.
Examples

Success#ifFailure

Success.from(value).ifFailure(doSomething); // void
// => Success(value)

Failure#ifFailure

Failure.from(error).ifFailure(doSomething); // doSomething([error])
// => Failure([error])

abstractifSuccess(method){Validation}

Applies the provided function to the value contain for a Success. Any return value from the function is ignored. If the instance is a Failure, the function is ignored and the instance is returned.
Name Type Description
method Consumer The function to invoke with the value.
Returns:
Type Description
Validation Current instance.
Examples

Success#ifSuccess

Success.from(value).ifSuccess(doSomething); // doSomething(value)
// => Success(value)

Failure#ifSuccess

Failure.from(error).ifSuccess(doSomething); // void
// => Failure([error])

isFailure(){Boolean}

Determines whether or not the instance is a Failure.
Returns:
Type Description
Boolean true if the instance is a Failure; false is not.
Examples

Success#isFailure

Success.from(value).isFailure();
// => false

Failure#isFailure

Failure.from(error).isFailure();
// => true

isSuccess(){Boolean}

Determines whether or not the instance is a Success.
Returns:
Type Description
Boolean true if the instance is a Success; false is not.
Examples

Success

Success.from(value).isFailure();
// => true

Failure#isSuccess

Failure.from(error).isFailure();
// => false

abstractmap(method){Validation}

Applies the provided function to the value contained for a Success which is, in turn, wrapped in a Success. If the instance is a Failure, the function is ignored and then instance is returned unchanged.
Name Type Description
method function The function to invoke with the value.
Returns:
Type Description
Validation Validation wrapped value mapped with the provided method.
Example
// Using lodash/fp/flow and sort
Success.from([1, 3, 2]).map(flow(sort, join(", ")));
// => Success("1, 2, 3")

Failure.from(error).map(flow(sort, join(", ")));
// => Failure([error])
See:

abstractorElse(value){*}

Returns the value if the instance is a Success otherwise returns the value supplied if the instance is a Failure.
Name Type Description
value * Value to use if the instace is a Failure.
Returns:
Type Description
*
Examples

Success#orElse

Success.from(value).orElse(otherValue);
// => value

Failure#orElse

Failure.from(error).orElse(otherValue);
// => otherValue

abstractorElseGet(method){*}

Return the value if the instance is a Success otherwise returns the value from the function provided.
Name Type Description
method Supplier The function supplying the optional value.
Returns:
Type Description
*
Examples

Success#orElseGet

Success.from(value).orElseGet(getOtherValue);
// => value

Failure#orElseGet

Failure.from().orElseGet(getOtherValue);
// => otherValue

abstractorElseThrow(method)

Applies the provided function to the value contain for a Failure and throws the resulting Error. If the instance is a Success, the function is ignored and the instance is returned.
Name Type Description
method function The function to invoke with the value.
Throws:
returned by the provided function.
Type
Error
Examples

Success#orElseThrow

Success.from(value).orElseThrow(createException); // void
// => Success(value)

Failure#orElseThrow

Failure.from(error).orElseThrow(createException); // throw createException([error])

abstracttoEither(either){Either}

Converts the validation to an Either using the provided Either implementation. Success becomes a Right and Failure becomes a Left.
Name Type Description
either Either Either implementation.
Returns:
Type Description
Either Either wrapped value.
Examples

Success#toEither

Success.from(value).toEither(Either);
// => Either.Right(value);

Failure#toEither

Failure.from(error).toEither(Either);
// => Either.Left([error]);

abstracttoMaybe(maybe){Maybe}

Converts the validation to an Maybe using the provided Maybe implementation. Success becomes a Just and Failure becomes a Nothing.
Name Type Description
maybe Maybe Maybe implementation.
Returns:
Type Description
Maybe Maybe wrapped value.
Examples

Success#toMaybe

Success.from(value).toMaybe(Maybe);
// => Maybe.Just(value);

Failure#toMaybe

Failure.from(error).toMaybe(Maybe);
// => Maybe.Nothing();

abstracttoPromise(promise){Promise}

Converts the validation to a Promise using the provided Promise implementation.
Name Type Description
promise Promise Promise implementation.
Returns:
Type Description
Promise Promise wrapped value.
Examples

Success#toPromise

const Bluebird = require("bluebird");

Success.from(value).toPromise(Bluebird);
// => Promise.resolve(value);

Failure#toPromise

const Bluebird = require("bluebird");

Failure.from(error).toPromise(Bluebird);
// => Promise.reject([error]);

abstracttoString(){String}

Returns a String representation of the Validation.
Returns:
Type Description
String String representation.
Examples

Success#toString

Success.from(1).toString();
// => "Validation.Success(1)"

Failure#toString

Failure.from("Error message").toString();
// => "Validation.Failure('Error message')"