nullable в Superstruct используется для описания
структур, допускающих значение null. Это один из ключевых
примитивов, позволяющий явно моделировать отсутствие значения, сохраняя
при этом строгую валидацию типов.
В отличие от ситуаций, где null может появляться неявно,
nullable делает это поведение частью схемы данных, а не
побочным эффектом.
Основная идея:
null;Функция nullable оборачивает любую структуру Superstruct
и расширяет допустимые значения.
import { string, nullable, assert } from 'superstruct';
const Name = nullable(string());
assert('Alex', Name); // корректно
assert(null, Name); // корректно
assert(123, Name); // ошибка
В этом примере структура Name допускает строку или
null, но исключает все остальные типы.
При проверке значений nullable работает как логическая
обёртка:
null → проверка проходит.null → выполняется валидация вложенной
структуры.import { number, nullable, validate } from 'superstruct';
const Age = nullable(number());
validate(25, Age); // [undefined, 25]
validate(null, Age); // [undefined, null]
validate('25', Age); // [Error]
Одно из частых заблуждений связано с различием между
nullable и optional.
Разрешает null как валидное значение.
Разрешает отсутствие значения (undefined).
import { optional, nullable, string } from 'superstruct';
const A = nullable(string());
const B = optional(string());
Сравнение поведения:
| Значение | nullable(string) | optional(string) |
|---|---|---|
| “text” | допустимо | допустимо |
| null | допустимо | недопустимо |
| undefined | недопустимо | допустимо |
Комбинация возможна:
import { nullable, optional, string } from 'superstruct';
const C = optional(nullable(string()));
Такой вариант допускает:
nullable часто применяется в объектах, где часть данных
может отсутствовать логически, но не структурно.
import { object, string, nullable } from 'superstruct';
const User = object({
name: string(),
middleName: nullable(string()),
});
Примеры:
validate(
{ name: 'Ivan', middleName: null },
User
);
validate(
{ name: 'Ivan', middleName: 'Petrovich' },
User
);
Ошибочные случаи:
validate(
{ name: 'Ivan', middleName: 123 },
User
);
nullable корректно работает с любыми типами Superstruct,
включая сложные композиции.
import { array, nullable, number } from 'superstruct';
const Scores = nullable(array(number()));
validate([1, 2, 3], Scores); // ок
validate(null, Scores); // ок
validate([1, '2'], Scores); // ошибка
nullable сохраняет поведение всех обёрнутых структур,
включая пользовательские проверки.
import { refine, nullable, string } from 'superstruct';
const NonEmptyString = refine(string(), 'NonEmptyString', (v) => v.length > 0);
const Field = nullable(NonEmptyString);
validate(null, Field); // ок
validate('hello', Field); // ок
validate('', Field); // ошибка
Важно: null проверку refine не проходит,
потому что обработка происходит до выполнения внутренних правил.
При нарушении правил nullable возвращает ошибку,
указывающую на несоответствие вложенной структуры.
Пример:
import { validate, nullable, number } from 'superstruct';
const Age = nullable(number());
const [error] = validate('abc', Age);
console.log(error);
Типичная ошибка будет указывать на ожидание number или
null.
В реальных схемах данных nullable часто используется для
полей, которые могут быть очищены пользователем или отсутствовать в
источнике данных.
import { object, string, nullable } from 'superstruct';
const Profile = object({
username: string(),
avatarUrl: nullable(string()),
bio: nullable(string()),
});
Такая модель позволяет:
null;undefined и null в
данных.При работе с массивами nullable может применяться как к
элементам, так и к самому массиву.
import { array, nullable, string } from 'superstruct';
const Tags = array(nullable(string()));
Допустимые значения:
['js', null, 'ts']
const Tags = nullable(array(string()));
Допустимые значения:
['js', 'ts']nullnullable не влияет на структуру данных вне валидации. Он
не преобразует значения и не модифицирует их.
Это означает:
null остаётся null;const [error, value] = validate('text', nullable(string()));
// value === 'text'
const Field = nullable(string());
Ожидание: поле может отсутствовать Реальность: отсутствие поля
(undefined) не разрешено
const Field = nullable(string());
Передача undefined приводит к ошибке, несмотря на
“логическое отсутствие значения”.
import { defaulted, nullable, string } from 'superstruct';
const Field = defaulted(nullable(string()), 'text');
Здесь null не заменяется значением по умолчанию, так как
он считается валидным значением.
Использование nullable часто связано с выбором стратегии
представления отсутствующих значений:
null — явное отсутствие значения;undefined — неопределённое состояние;nullable фиксирует первый вариант как часть схемы
данных, делая его строго контролируемым элементом валидации.