Skip to content

Instantly share code, notes, and snippets.

@gillchristian
Created January 20, 2022 15:04
Show Gist options
  • Save gillchristian/6b6abedbce5809b659e77bff3d953962 to your computer and use it in GitHub Desktop.
Save gillchristian/6b6abedbce5809b659e77bff3d953962 to your computer and use it in GitHub Desktop.
/**
* We could use `Either<string, T>` as a validaiton result. But the problem is,
* we wouldn't be able to accumulate the errors. The `Validation` types enables
* that for us.
*
* ```ts
* type Validation<E, T> = Either<NonEmptyArray<E>, T>
* ```
*
* @example
* import * as Either from 'fp-ts/Either';
* import { pipe } from 'fp-ts/function';
* import { sequenceT } from 'fp-ts/Apply';
* import { getSemigroup, NonEmptyArray } from 'fp-ts/NonEmptyArray';
*
* const notAllowedUrls = (s: string) =>
* s.includes('facebook') ? Either.left('Not allowed') : Either.right(s);
*
* const wordLimit = (s: string) =>
* s.split(' ').length > 5 ? Either.left('Too many words') : Either.right(s);
*
* const hasBannedWords = (s: string) =>
* s.includes('BAD_WORD') ? Either.left('Includes bad word') : Either.right(s);
*
* const applicativeValidation =
* Either.getApplicativeValidation(getSemigroup<string>());
*
* const validateText = (s: string) =>
* pipe(
* sequenceT(applicativeValidation)(
* liftValidation(notAllowedUrls)(s),
* liftValidation(wordLimit)(s),
* liftValidation(hasBannedWords)(s)
* ),
* Either.map(() => s)
* );
*
* validateText('BAD_WORD one two three four five six');
* //=> Either.left(['Too many words', 'Includes bad word'])
*
* validateText('I am good');
* //=> Either.right('I am good')
*/
export function liftValidation<E, A>(
check: (a: A) => Either.Either<E, A>
): (a: A) => Either.Either<NonEmptyArray.NonEmptyArray<E>, A> {
return (a) =>
pipe(
check(a),
Either.mapLeft((a) => [a])
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment