Skip to content

Instantly share code, notes, and snippets.

@Dremora
Last active October 14, 2021 02:49
Show Gist options
  • Save Dremora/21f5454f5cd999dbeeed694e044e0390 to your computer and use it in GitHub Desktop.
Save Dremora/21f5454f5cd999dbeeed694e044e0390 to your computer and use it in GitHub Desktop.
import moment from 'moment';
export const EMAIL_REGEXP = /[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])/;
const isInRange = (date: moment, [from, to]: [moment, moment]): boolean =>
date.isSameOrAfter(from, 'day') && date.isSameOrBefore(to, 'day');
type ValidatorReturn = string | null;
type Validator<T> = (value: T) => ValidatorReturn;
type Predicate<T> = (value: T) => boolean;
export const validate =
<T>(predicate: Predicate<T>, message: string) =>
(value: T): ValidatorReturn =>
predicate(value) ? null : message;
export const required = (value: string): boolean => !!value.trim().length;
export const is =
(valueToMatch: unknown) =>
(value: unknown): boolean =>
value === valueToMatch;
const emptyPredicate = (value: string): boolean => value === "";
export const empty: Validator<string> = validate(
emptyPredicate,
"This field is required"
);
export const not =
<T>(validator: Validator<T>): Validator<T> =>
(value: T): ValidatorReturn =>
validator(value) ? null : "Not valid";
export const string =
(validator: Validator<string>) =>
(value: unknown): ValidatorReturn =>
typeof value === "string" ? validator(value) : "Not a string";
const minLengthPredicate =
(length: number) =>
(value: string): boolean =>
value.length >= length;
export const minLength = (length: number) =>
validate(minLengthPredicate(length), "Too short");
const maxLengthPredicate =
(length: number) =>
(value: string): boolean =>
value.length <= length;
export const maxLength = (length: number) =>
validate(maxLengthPredicate(length), "Too long");
export const exactLength =
(length: number) =>
(value: string): boolean =>
typeof value === "string" ? value.length === length : length === 0;
export const matches =
(regex: RegExp) =>
(value: unknown): boolean =>
regex.test(typeof value === "string" ? value : "");
export const and =
<T>(...validators: Validator<T>[]) =>
(value: T): ValidatorReturn =>
validators.reduce<ValidatorReturn>(
(error, validator) => (error ? error : validator(value)),
null
);
export const or =
<T>(...validators: Validator<T>[]) =>
(value: T): ValidatorReturn =>
validators.reduce<ValidatorReturn>(
(error, validator) => (error ? validator(value) : null),
"error"
);
export const matches = (regex: RegExp) => (value: unknown): boolean => regex.test(typeof value === 'string' ? value : '');
export const email = (value: unknown = ''): boolean => (typeof value === 'string' ? !!value.match(EMAIL_REGEXP) : false);
export const dateInRange = (minDate: moment, maxDate: moment) => (value: unknown) =>
typeof value === 'string' && isInRange(moment(value), [minDate, maxDate]);
export const dateValid = (value: unknown) => typeof value === 'string' && moment(value).isValid();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment