Маски и валидация
Маска отвечает за вид значения, валидация — за правильность. Маска не даст ввести букву в телефон, но не знает, что номер не дописан или что у ИНН неверная контрольная сумма.
Проверить, что маска заполнена
isComplete — все обязательные позиции заполнены. isValid — заполнено и правильно по смыслу (что именно проверяется — в Готовых масках):
ts
isComplete('+7 (999) 123-45', phone()); // false
isComplete('+7 (999) 123-45-67', phone()); // true
// filled and correct
isValid('31.02.2026', date()); // false — no such date
isValid('4111 1111 1111 1112', card()); // false — wrong check digitСо схемой tinyval
Снимите маску в preprocess — дальше проверяется и попадает в data чистое значение:
ts
import { validate, object, string, pipe, preprocess, length, pattern, coerce } from 'tinyval';
import { unmask, isComplete } from 'tinyval-mask';
import { phone, card, money } from 'tinyval-mask/presets';
const phoneMask = phone();
const cardMask = card();
const moneyMask = money();
// the mask is removed first, then the clean value is validated
const unmasked = (m: Parameters<typeof unmask>[1]) => (v: unknown) => (v === '' || v == null ? v : unmask(String(v), m));
const Order = object({
phone: preprocess(unmasked(phoneMask), pipe(string(), length(11))),
card: preprocess(unmasked(cardMask), pipe(string(), pattern(/^\d{16,19}$/))),
amount: preprocess(unmasked(moneyMask), coerce.number()),
});
validate(Order, { phone: '+7 (999) 123-45-67', card: '4276 1234 5678 9012', amount: '1 500,50' }).data;
// { phone: '79991234567', card: '4276123456789012', amount: 1500.5 }- Пустое значение остаётся пустым — работает правило пустых значений и
optional. - То же на сервере: маски — чистые функции, поэтому
unmaskнормализует телефоны, пришедшие в любом формате.