Validation
folktale.validation
- Models one or more validations as either
Validation.Success
orValidation.Failure
. Validation.Success
contains the valid value andValidation.Failure
contains an accumulation of messages from any failed validation.- Validation is like a Semigroup because it has the method
concat
. - Validation is not a Monad because it doesn't have a
chain
method.
Combining
Validations can be combined in two ways.
concat
One validation can be concatenated onto another:
validation1(value).concat(validation2(value);
collect
Multiple validations can be concatenated together:
const isValid = (value) => collect([
validation1(value),
validation2(value),
])
These can then be used as a single validation and collected themselves:
const anotherIsValid = (value) => collect([
isValid(value),
validation3(value),
])
Transformation
matchWith
To map the result to a different function depending on whether it is a Validation.Success
or a Validation.Failure
:
result.matchWith({
Success: ({value}) => `Value: ${value}`,
Failure: () => `Failed: ${value}`,
})
map
To perform an action on the result only if it is Success, map
can be used. If the result is a Validation.Failure
, it will just return that Validation.Failure
, but if the result is Validation.Success
, its value will be passed in to the function supplied, and it will return whatever the function returns as the value
of a Validation.Success
.
const value = validation.map(example);
mapFailure
Conversely the value(s) of a Validation.Failure
can also be transformed using mapFailure
.
const value = validation.mapFailure(example);
Examples
Basic
const isValueNumber = (value) =>
isNumber(value) ?
Success(value) :
Failure([`Must be a number`])
const isValueEven = (value) =>
isEven(value) ?
Success(value) :
Failure([`Must be even`])
const isValidValue = (value) =>
Success().concat(isValueNumber(value))
.concat(isValueEven(value))
const validValue = isValidValue(2);
const invalidValue = isValidValue('x');
console.log('Valid Value', validValue.value);
console.log('Invalid Value', invalidValue.value);
Using collect
const isValueNumber = (value) =>
isNumber(value) ?
Success(value) :
Failure([`Must be a number`])
const isValueEven = (value) =>
isEven(value) ?
Success(value) :
Failure([`Must be even`])
const isValidValue = (value) => collect([
isValueNumber(value),
isValueEven(value)
])
const validValue = isValidValue(2);
const invalidValue = isValidValue('x');
console.log('Valid Value', validValue.value);
console.log('Invalid Value', invalidValue.value);