Декоратор @IsNotIn в библиотеке
class-validator используется для валидации значений на
принадлежность к «запрещённому набору». Его задача — убедиться, что
проверяемое значение не входит в заранее заданный
массив.
Основная идея заключается в инверсии проверки принадлежности: если значение найдено в списке — валидация считается проваленной.
@IsNotIn(values: any[], validationOptions?: ValidationOptions)
values — массив значений, которые считаются
недопустимымиvalidationOptions — объект настройки сообщения и
поведения ошибкиВнутри механизм реализует простую проверку:
Array.includes)Таким образом, @IsNotIn является противоположностью
@IsIn.
import { IsNotIn } from 'class-validator';
class CreateUserDto {
@IsNotIn(['admin', 'root', 'superuser'])
username: string;
}
В этом примере поле username не может принимать значения
admin, root, superuser.
Проверка выполняется строго, без приведения типов:
@IsNotIn([1, 2, 3])
value: number;
value = 1 → ошибкаvalue = "1" → допустимо (разные типы)value = 4 → допустимоИспользуется строгое сравнение аналогичное ===.
import { IsNotIn } from 'class-validator';
class ProductDto {
@IsNotIn(['test', 'demo'], {
message: 'Недопустимое значение для поля name'
})
name: string;
}
Сообщение может быть строкой или функцией:
message: ({ value }) => `Значение "${value}" запрещено`
Список запрещённых значений может формироваться динамически:
const bannedNames = ['admin', 'system', 'null'];
class UserDto {
@IsNotIn(bannedNames)
username: string;
}
При этом массив фиксируется в момент объявления класса, а не пересчитывается на каждый запрос.
По умолчанию class-validator не выполняет проверку, если
значение отсутствует, если не заданы дополнительные ограничения:
class UserDto {
@IsNotIn(['admin'])
username?: string;
}
undefined → пропуск проверкиnull → поведение зависит от наличия
@IsDefined, @IsOptionalДля строгой проверки обычно комбинируется:
import { IsNotIn, IsDefined } from 'class-validator';
class UserDto {
@IsDefined()
@IsNotIn(['admin'])
username: string;
}
@IsNotIn часто используется вместе с другими
ограничениями:
import { IsString, MinLength, IsNotIn } from 'class-validator';
class AccountDto {
@IsString()
@MinLength(3)
@IsNotIn(['guest', 'anonymous'])
nickname: string;
}
Порядок декораторов не влияет на итоговую логику, но влияет на читаемость и диагностику ошибок.
Типичный сценарий — проверка входных данных:
class RegisterDto {
@IsNotIn(['admin', 'root'])
login: string;
@IsNotIn(['123456', 'password', 'qwerty'])
password: string;
}
Каждое поле проверяется независимо, и ошибки формируются отдельно.
При использовании class-transformer данные сначала
приводятся к экземпляру класса, затем выполняется валидация.
Важно учитывать:
transform: trueПример:
// вход
{ value: "1" }
@IsNotIn([1])
value: number;
При трансформации в число проверка станет невалидной, иначе — допустимой.
При нарушении правила возвращается объект ошибки:
{
"property": "username",
"constraints": {
"isNotIn": "username should not be one of the following values: admin, root"
}
}
Ключ isNotIn формируется автоматически и может быть
переопределён через message.
@IsNotIn(['a', 'b'], {
message: 'Недопустимое значение',
context: {
errorCode: 'FORBIDDEN_VALUE'
}
})
field: string;
context позволяет передавать дополнительные метаданные в
систему обработки ошибок.
@IsNotIn не предназначен для проверки массива значений
целиком. Он проверяет одно значение, а не элементы
массива.
Неправильное ожидание:
@IsNotIn(['a', 'b'])
tags: string[]; // некорректная логика использования
В этом случае валидация сравнивает сам массив с элементами, что не даёт ожидаемого результата.
Для массивов требуется использование @ArrayNotContains
или кастомной валидации.
@IsIn — значение должно присутствовать в списке@IsNotIn — значение не должно присутствовать в
списке@IsIn(['user', 'admin'])
role: string;
@IsNotIn(['banned', 'deleted'])
status: string;
Эти декораторы часто используются совместно для разных полей модели.
@IsNotIn([])
value: string;
Пустой список означает отсутствие ограничений, и любое значение считается допустимым.
Декоратор часто применяется для ограничения:
const RESERVED_WORDS = ['null', 'undefined', 'admin', 'system'];
class ProfileDto {
@IsNotIn(RESERVED_WORDS)
slug: string;
}
@IsOptional при допустимости пустых
значенийТипизация не влияет на runtime-проверку. Даже при:
@IsNotIn(['1', '2'])
value: string;
валидатор работает исключительно с фактическим значением во время выполнения, игнорируя типовую систему.
При большом количестве правил:
@IsNotIn имеет сложность O(n)Set
и кастомных валидаторовconst banned = new Set(['a', 'b', 'c']);
@IsNotIn корректно работает в связке с: