@NotEquals

Декоратор @NotEquals в библиотеке class-validator используется для проверки неравенства значения свойства заранее заданной константе. Валидация выполняется по строгому сравнению (=== / !== в терминах семантики JavaScript), что делает поведение предсказуемым при работе с примитивами.

Основная задача — гарантировать, что значение поля не совпадает с указанным запрещённым значением. Это применяется для фильтрации недопустимых дефолтов, маркеров, системных флагов или зарезервированных значений.


Базовая форма использования

Декоратор принимает одно обязательное значение — то, с чем производится сравнение.

import { NotEquals } from 'class-validator';

class UserDto {
  @NotEquals('admin')
  role: string;
}

В данном случае значение role не должно быть строкой "admin". Любое другое значение проходит проверку.


Принцип работы

@NotEquals реализует простое отрицание равенства:

  • значение проходит валидацию, если value !== comparisonValue
  • значение не проходит, если value === comparisonValue

Сравнение осуществляется без приведения типов, что критично для строгой типизации DTO-слоя.

Примеры поведения:

Значение Запрещённое значение Результат
“user” “admin” проходит
“admin” “admin” ошибка
1 1 ошибка
“1” 1 проходит

Сообщение об ошибке

По умолчанию библиотека формирует стандартное сообщение, но его можно переопределить через опции:

import { NotEquals } from 'class-validator';

class ProductDto {
  @NotEquals('draft', {
    message: 'status не может быть draft',
  })
  status: string;
}

Сообщения часто используются в API-слоях для формирования читаемых ошибок валидации.


Валидация числовых значений

@NotEquals применяется не только к строкам, но и к числам:

class ConfigDto {
  @NotEquals(0)
  retries: number;
}

В этом случае значение 0 запрещено, например, для предотвращения отключённой логики повторных попыток.


Поведение с булевыми значениями

Булевы значения часто используются как переключатели состояния:

class FeatureDto {
  @NotEquals(false)
  enabled: boolean;
}

Такой подход применяется, когда false является недопустимым состоянием (например, обязательное включение функциональности).


Работа с undefined и null

@NotEquals не выполняет автоматическую проверку на наличие значения. Если свойство отсутствует, поведение зависит от дополнительных декораторов:

import { NotEquals, IsDefined } from 'class-validator';

class ExampleDto {
  @IsDefined()
  @NotEquals('none')
  mode: string;
}

Без @IsDefined() значение undefined может пройти проверку, так как undefined !== 'none'.


Комбинация с другими валидаторами

@NotEquals часто используется в связке с другими ограничениями:

import { NotEquals, IsString, Length } from 'class-validator';

class AccountDto {
  @IsString()
  @Length(3, 20)
  @NotEquals('root')
  username: string;
}

Такая композиция формирует более строгую бизнес-логику: имя должно быть строкой, иметь длину и не совпадать с системным идентификатором.


Использование с массивами и вложенными объектами

@NotEquals не предназначен для глубокого сравнения структур. При применении к массивам сравнение происходит по ссылке:

class DataDto {
  @NotEquals([1, 2, 3])
  values: number[];
}

В этом случае проверяется не содержимое массива, а его ссылка, что делает такой подход практически бесполезным для структурных данных.

Для вложенных объектов валидатор также сравнивает ссылки:

class Inner {
  x: number;
}

class Outer {
  @NotEquals({ x: 1 })
  data: Inner;
}

Сравнение выполняется некорректно для глубоких структур, что является важным ограничением.


Использование в бизнес-логике DTO

Валидация через @NotEquals часто применяется для предотвращения попадания запрещённых маркеров в систему:

class OrderDto {
  @NotEquals('test')
  comment: string;
}

Такие значения могут использоваться фронтендом или тестовыми окружениями, но должны блокироваться в продакшене.


Поведение при преобразовании типов

Библиотека class-transformer часто используется совместно с class-validator для преобразования входных данных.

Важно учитывать, что @NotEquals работает уже после трансформации:

import { Type } from 'class-transformer';
import { NotEquals } from 'class-validator';

class PaymentDto {
  @Type(() => Number)
  @NotEquals(0)
  amount: number;
}

В этом примере строковое значение "0" будет преобразовано в число 0, после чего сработает валидация.


Поведение при строгой и нестрогой проверке входных данных

@NotEquals не зависит от режима строгой валидации. Однако результат может изменяться в зависимости от предварительной обработки данных:

  • без трансформации "10" и 10 считаются разными
  • с трансформацией типы приводятся, и сравнение становится более предсказуемым

Типичные сценарии применения

Запрет системных значений

class LogDto {
  @NotEquals('SYSTEM')
  source: string;
}

Запрет дефолтных значений формы

class FilterDto {
  @NotEquals('all')
  category: string;
}

Запрет нулевых конфигураций

class RetryDto {
  @NotEquals(0)
  delay: number;
}

Ограничения декоратора

Функциональность @NotEquals ограничена простыми типами:

  • отсутствует глубокое сравнение объектов
  • отсутствует частичное сравнение структур
  • не учитывается контекст выполнения
  • не выполняется нормализация значений

По сути, это инструмент для атомарных проверок.


Внутренняя логика проверки

На уровне реализации используется простой constraint, который принимает значение из декоратора и сравнивает его с текущим значением свойства:

  • хранится эталонное значение
  • при валидации выполняется оператор нестрогого сравнения с учётом JavaScript-правил
  • результат инвертируется (равно → ошибка, не равно → успех)

Такая модель делает валидатор лёгким и предсказуемым.


Особенности работы с типами данных

Поведение различается в зависимости от типа:

  • строки: сравнение посимвольно
  • числа: строгое числовое сравнение
  • boolean: прямое сравнение true/false
  • объекты: сравнение по ссылке
  • массивы: сравнение по ссылке

Это накладывает ограничения на использование в сложных структурах данных.


Практика построения правил

@NotEquals редко используется как единственный валидатор. Чаще он выступает частью набора правил, формирующих ограничения доменной модели:

  • запрет служебных значений
  • исключение резервированных слов
  • фильтрация тестовых данных
  • контроль дефолтов API

Комбинация с @IsEnum, @IsString, @IsOptional, @ValidateIf позволяет формировать гибкие схемы проверки входных данных без усложнения бизнес-логики.