Валидация строковых значений в class-validator строится
на декларативном описании ограничений, которые накладываются на свойства
классов. Строка рассматривается не как «просто текст», а как объект с
набором характеристик: длина, формат, допустимые символы, наличие
пробелов, обязательность заполнения и контекст использования.
Работа с текстовыми полями почти всегда требует комбинации нескольких декораторов, поскольку одно ограничение редко описывает бизнес-правило полностью.
import { IsString } from "class-validator";
class UserDto {
@IsString()
username: string;
}
@IsString() проверяет, что значение действительно
является строкой в момент валидации. Числа, null,
undefined, объекты и массивы будут считаться
невалидными.
Одной из типичных проблем является различие между отсутствием значения и пустой строкой. Валидация строк почти всегда требует явного управления этими состояниями.
import { IsString, IsNotEmpty } from "class-validator";
class UserDto {
@IsString()
@IsNotEmpty()
username: string;
}
@IsNotEmpty() проверяет, что строка существует и
содержит хотя бы один символ. Значение "" считается
недопустимым, как и null или undefined.
Пробельные строки (" ") формально не считаются
пустыми. Это приводит к необходимости дополнительной логики.
import { Matches } from "class-validator";
class UserDto {
@IsString()
@Matches(/\S/, { message: "Строка не должна состоять только из пробелов" })
username: string;
}
Регулярное выражение \S гарантирует наличие хотя бы
одного непробельного символа.
Контроль длины является одной из наиболее распространённых форм валидации текстовых данных.
import { MinLength, MaxLength } from "class-validator";
class UserDto {
@IsString()
@MinLength(3)
@MaxLength(20)
username: string;
}
@MinLength(n) требует минимальное количество символов.
@MaxLength(n) ограничивает максимальную длину.
Важно учитывать, что длина считается в символах JavaScript-строки, а не в байтах. Это означает, что эмодзи и некоторые Unicode-символы могут занимать больше одного «визуального символа» при хранении.
import { Length } from "class-validator";
class UserDto {
@IsString()
@Length(3, 20)
username: string;
}
@Length(min, max) эквивалентен комбинации минимального и
максимального ограничения и используется для компактности.
Регулярные выражения дают максимальную гибкость при описании формата
строки. В class-validator для этого используется декоратор
@Matches.
import { Matches } from "class-validator";
class UserDto {
@IsString()
@Matches(/^[a-zA-Z0-9_]+$/, {
message: "Разрешены только латинские буквы, цифры и символ '_'"
})
username: string;
}
Данный пример ограничивает строку набором символов, формируя типичный формат «логина».
Регулярные выражения часто применяются для описания доменных сущностей:
class ProductDto {
@IsString()
@Matches(/^SKU-[0-9]{6}$/)
sku: string;
}
Строка должна строго соответствовать шаблону
SKU-XXXXXX.
Валидация строк редко отделяется от нормализации. Часто входные данные содержат лишние пробелы, которые необходимо учитывать.
import { Transform } from "class-transformer";
import { IsString } from "class-validator";
class UserDto {
@Transform(({ value }) => typeof value === "string" ? value.trim() : value)
@IsString()
username: string;
}
trim() удаляет пробелы по краям строки, снижая
вероятность некорректного прохождения @IsNotEmpty().
Не все строковые поля являются обязательными. В
class-validator для этого используется
@IsOptional().
import { IsOptional, IsString, MaxLength } from "class-validator";
class UserDto {
@IsOptional()
@IsString()
@MaxLength(100)
bio?: string;
}
Поведение @IsOptional() заключается в том, что валидация
остальных декораторов не выполняется, если значение равно
undefined или null.
Важно: пустая строка "" не считается отсутствием
значения.
TypeScript-типизация не заменяет runtime-валидацию. Следующий код
корректен с точки зрения TypeScript, но небезопасен без
class-validator:
class UserDto {
username: string;
}
Если в API приходит 123, TypeScript не защитит от этого.
@IsString() выполняет проверку уже во время выполнения.
Строковые поля в прикладных системах почти всегда требуют комплексной проверки.
class UserDto {
@Transform(({ value }) => typeof value === "string" ? value.trim() : value)
@IsString()
@IsNotEmpty()
@MinLength(3)
@MaxLength(20)
@Matches(/^[a-zA-Z0-9_]+$/)
username: string;
}
Здесь одновременно контролируются:
Часто строки используются как идентификаторы сущностей.
class CommentDto {
@IsString()
@Matches(/^[a-f0-9]{24}$/)
postId: string;
}
Такой формат характерен для MongoDB ObjectId.
Валидация строк может зависеть от других полей.
import { ValidateIf, IsString } from "class-validator";
class ProfileDto {
@ValidateIf(o => o.nickname !== undefined)
@IsString()
nickname: string;
}
ValidateIf позволяет включать или отключать проверки
динамически.
Строки в JavaScript основаны на UTF-16, что влияет на поведение длины и регулярных выражений.
class UserDto {
@IsString()
@MaxLength(10)
name: string;
}
В этом случае строка, содержащая сложные символы (например, эмодзи), может занимать больше визуального пространства, чем ожидается.
Регулярные выражения также должны учитывать Unicode-флаги:
@Matches(/^[\p{L}\s]+$/u)
name: string;
Флаг u включает Unicode-сопоставление, позволяя
учитывать буквы разных языков.
Когда встроенных декораторов недостаточно, используется пользовательская логика.
import { ValidatorConstraint, ValidatorConstraintInterface } from "class-validator";
@ValidatorConstraint({ name: "isNoWhitespaceOnly", async: false })
class IsNoWhitespaceOnly implements ValidatorConstraintInterface {
validate(value: string) {
return typeof value === "string" && value.trim().length > 0;
}
defaultMessage() {
return "Строка не должна состоять только из пробелов";
}
}
Применение:
import { Validate } from "class-validator";
class UserDto {
@IsString()
@Validate(IsNoWhitespaceOnly)
username: string;
}
Slug используется в URL и требует строгого формата.
class ArticleDto {
@IsString()
@Matches(/^[a-z0-9]+(?:-[a-z0-9]+)*$/)
slug: string;
}
Правила:
Каждый декоратор поддерживает переопределение сообщений об ошибке.
class UserDto {
@IsString({ message: "Значение должно быть строкой" })
@MinLength(3, { message: "Минимальная длина — 3 символа" })
username: string;
}
Сообщения часто используются для формирования API-ответов, пригодных для фронтенда.
Если строка не проходит несколько проверок, возвращается массив ошибок, где каждая ошибка соответствует конкретному декоратору. Это позволяет точно определять источник проблемы: тип, длина, формат или обязательность.
Комбинированная валидация строк в class-validator
строится на принципе композиции: каждое ограничение добавляет отдельный
слой логики, а итоговая модель представляет собой совокупность правил,
описывающих допустимое состояние строкового поля в системе.