Validation
folktale.validation
- Models one or more validations as either
Validation.SuccessorValidation.Failure. Validation.Successcontains the valid value andValidation.Failurecontains 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
chainmethod.
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);