Странные применения валидации

от автора

Валидаторы нужны для валидации. Давайте ради забавы забудем об этом. Давайте с помощью валидатора пройдёмся по вложенной структуре данных. Сумасшествие, скажете вы!

image Nordic YES

По чём бежать будем?

Давайте бежать по телефонной книге:

const phoneBook = {   andrew: ["+345356245254", "+313232312312"],   vasilina: ["+132313123123"],   serhiy: ["+587234878234", "+321323124123"], };

Что хотим получить?

Давайте получим список всех номеров.

Как мы это сделаем?

Мы сделаем это в 4 шага:

  • Подключим библиотеку для валидации данных
  • Создадим обычную функцию валидации
  • Добавим побочный эффект собирания номеров в массив
  • Обернём в функцию

Будем использовать библиотеку валидации quartet:

import { v } from "quartet";

Напишем функцию валидации:

const checkPhoneBook = v({   [v.rest]: v.arrayOf(v.string), });

Теперь мы можем проверить, является ли некое значение телефонной книгой:

checkPhoneBook({}); // true checkPhoneBook({ andrew: ["123321"] }); // true checkPhoneBook({ andrew: null }); // false

Теперь добавим немного сумасшествия: проверяя элемент списка номеров будем его добавлять в массив.

const phoneNumbers = []; const checkAndCollect = v({   [v.rest]: v.arrayOf(     v.and(       v.string,       v.custom((phoneNumber) => {         phoneNumbers.push(phoneNumber);         return true;       })     )   ), });

Вызовем эту функцию валидации на конкретной телефонной книге:

checkAndCollect({   andrew: ["+345356245254", "+313232312312"],   vasilina: ["+132313123123"],   serhiy: ["+587234878234", "+321323124123"], });

Вернулось true. Но нас это не интересует! Главное: в массиве phoneNumbers теперь хранятся все номера.

console.log(phoneNumbers); // [ //   '+345356245254', //   '+313232312312', //   '+132313123123', //   '+587234878234', //   '+321323124123' // ]

Обернём это в функцию для «переиспользования»:

import { v } from "quartet";  /**  * @param {Record<string, string[]>} phoneBook  * @returns {string[]} phone numbers  */ function collectPhoneNumbers(phoneBook) {   const phoneNumbers = [];    const checkAndCollect = v({     [v.rest]: v.arrayOf(       v.and(         v.string,         v.custom((phoneNumber) => {           phoneNumbers.push(phoneNumber);           return true;         })       )     ),   });    checkAndCollect(phoneBook);    return phoneNumbers; }

Оценка

Использование таких трюков может быть забавным. Но я бы не писал так в production коде. И по четырем причинам:

  • Это не оптимальное решение по скорости работы. Создание функции валидации для итерации по книге номеров — лишнее действие.
  • Это не идиоматический код. Библиотека валидации не предназначена для итераций.
  • Это опасный код. Библиотека может поменять внутренние правила проверки и это может привести к повторным вызовам карточного валидатора.
  • Есть код более подходящий для этой задачи:

/**  * @param {Record<string, string[]>} phoneBook  * @returns {string[]} phone numbers  */ function collectPhoneNumbers(phoneBook) {   const phoneNumbers = [];    const personNames = Object.keys(phoneBook);    for (const personName of personNames) {     const personPhoneNumbers = phoneBook[personName];     phoneNumbers.push(...personPhoneNumbers);   }    return phoneNumbers; }

Послесловие

Вот такую забаву я придумал в Воскресение вечером. А что странного приходит в вашу голову? Напишите в комментах.

ссылка на оригинал статьи https://habr.com/ru/post/535258/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *