Встретившись в многочисленных местах разработки на Javascript с ситуациями, где необходимо было проводить валидацию значений, стало понятно, что необходимо как-то решить этот вопрос. С этой целью была поставлена следующая задача:
Разработать библиотеку, которая будет давать возможность: В основе которой будет: Для достижения этих целей была разработана библиотека валидации quartet. В основе большинства систем, которые расчитываются быть применимыми в широком кругу задач, лежат простейшие элементы: действия, данные и алгоритмы. А также методы их композиции — с целью из простейших элементов собрать что-то более сложное для решения более сложных задач. В основе библиотеки quartet — лежит понятие валидатора. Валидаторами в данной библиотеке являются функциями следующего вида В данном определении есть несколько вещей, которые стоит описать подробнее: function(...): boolean — говорит о том, что валидатор — вычисляет результат валидации, и результатом валидации является булевое значение — истинно или ложно, соответственно валидно или не валидно value: any — говорит о том, что валидатор — вычисляет результат валидации значения, которое может быть любым значением javascript'a. Валидатор либо относит данное валидируемое значение к валидным или либо к невалидным. { key: string|int, parent: any }, ... — говорит о том, валидируемое значение может быть в разных контекстах в зависимости от того, на каком уровне вложенности находится значение. Покажем это на примерах Пример значения без какого-либо контекста Пример значения в контексте массива Пример значения в контексте объекта Так как структуры в объекте могут иметь бо́льшую вложенность, то имеет смысл говорить и о множестве контекстов И так далее. Данное определение валидатора должно вам напомнить определение функций, которые передаются в качестве аргумента в методы массивов, такие как: map, filter, some, every и тд. Валидатор в данном случае является более обобщённой функцией — он принимает не только индекс элемента в массиве и массив, но и индекс массива — в его родителе и его родителя и так далее. Кирпичи, описанные выше, ничем не выделяются в среде других "решений-камней", которые валяются на костыльном "пляже" javascript. Поэтому давайте построим из них, что-нибудь более стройное и интересное. Для этого у нас есть композиция. Согласитесь, было бы удобно валидировать объекты таким образом, чтобы само описание валидации совпадало с описанием объекта. Для этого мы будем использовать объектную композицию валидаторов. Она выглядит следующим образом: Как видим, из разных кирпичей-валидаторов, определённых для конкретных полей, мы можем собрать валидатор объекта — некоторое "маленькое здание", в котором ещё довольно тесно — но уже лучше чем без него. Для этого мы используем композитор валидаторов v. Всякий раз, встречая объектный литерал v на месте валидатора, он будет рассматривать его как объектную композицию, превращая его в валидатор объекта по его полям. Иногда мы не можем описать все поля. Например, когда объект является словарём данных: Как мы увидели выше, существует необходимость переиспользования простых валидаторов. В данных примерах нам уже пришлось использовать "валидатор типа строки" уже два раза. Для того, чтобы укоротить запись и повысить её читаемость в библиотеке quartet используются строковые синонимы валидаторов. Всякий раз, когда композитор валидаторов встречает строку на месте, где должен быть валидатор, он ищет в словаре соответствующий ей валидатор и использует его. По умолчанию в библиотеке уже определены самые распространённые валидаторы. Рассмотрим примеры: и множество других описаных в документации. Композитор валидаторов(функция v) также является фабрикой валидаторов. В том смысле, что содержит множество полезных методов, которые возвращают  Например, посмотрим на валидацию массива: чаще всего она состоит из проверки типа массива и проверки всех его элементов. Воспользуемся для этого методом v.arrayOf(elementValidator). Для примера возьмём массив точек с именами. Так как массив точек — это массив объектов, то имеет смысл использовать объектную композицию для валидации элементов массива. Теперь, с помощью фабричного метода v.arrayOf, создадим валидатор всего массива. Посмотрим как работает данный валидатор: Это только один из фабричных методов, каждый из которых описан в документации Как вы видели выше, v.rest также является фабричным методом, который возвращает объектную композицию, которая проверяет все поля не указанные в объектной композиции. А значит, может быть встроен в другую объектную композицию с помощью spread-operator. Приведём в качестве примера использования нескольких из них: Часто бывает так, что валидные данные принимают различные формы, например: Для организации валидации вариантов предусмотрен отдельный вид композиции — вариантная композиция. Она представляется массивом валидаторов возможных вариантов. Валидным считается объект, когда хоть один из валидаторов сообщил о его валидности. Рассмотрим пример c валидацией идентификаторов: Пример с валидацией точек: Таким образом всякий раз, когда композитор видит массив, он будет считать его композицией валидаторов-элементов этого массива таким образом, что когда один из них посчитает значение валидным — расчёт валидации остановится — и значение будет признано валидным. Как видим композитор считает валидатором не только функцию валидатор, но и всё, что может привести к функции валидатору. Все данные варианты валидаторов валидны и могут использоваться в любом месте внутри схемы, в котором должен стоять валидатор. В итоге схема работы всегда такая: v(schema) возвращает функцию валидации. Далее эта функция валидации вызывается на конкретных значениях:
v(schema)(value[, ...parents])  — Нет пока ещё не одной
 — Будут! Бывает так, что данные невалидны и нам нужно уметь определить причину невалидности. Для этого в библиотеке quartet предусмотрен механизм объяснений. Он состоит в том, что в случае, когда валидатор, будь-то внутренний или внешний, обнаружит невалидность проверяемых данных — он должен отправить пояснительную записку. Для этих целей используется второй аргумент композитора валидаторов v. Он добавляет сайд-еффект отправки пояснительной записки в массив v.explanation в случае невалидности данных. Пример, пусть мы валидируем массив, и хотим узнать номера всех элементов, которые невалидны и их значение: Как видим, выбор объяснения зависит от задачи. Иногда оно даже не нужно. Иногда нам необходимо что-то сделать с невалидными полями. В таких случаях имеет смысл использовать имя невалидного поля как объяснение: Имея данный механизм объяснений, можно реализовать любое поведение, связанное с результатами валидации. Пояснением может быть всё что угодно: Исправлять ошибки валидации — не редкая задача. Для этих целей в библиотеке используются валидаторы с побочным эффектом, который запоминает место ошибки и как её исправить. В данной библиотеке также существуют утилитные методы для действий связанных с валидацией: Заданные задачи были решены следующими способами: Данное решение было разработано для быстрого и удобного создания функций валидаторов с возможностью встраивания пользовательских функций валидации. Поэтому, если таковые будут, любые правки, критика, варианты улучшения от прочитавших данную статью приветствуются. Спасибо за внимание.
 Frontend developer