В библиотеке class-validator значительная часть проверки данных
строится вокруг декораторов, работающих на уровне строковых значений.
Среди таких инструментов особое место занимают
@IsLowercase() и @IsUppercase(),
предназначенные для строгой проверки регистра символов в строках.
Эти валидаторы используются в DTO-моделях и классах данных для контроля формата входных значений, особенно когда регистр является частью бизнес-логики: коды, идентификаторы, токены, региональные обозначения, пользовательские алиасы и нормализованные строки.
Декоратор @IsLowercase() гарантирует, что строка
содержит только символы в нижнем регистре. Любой символ верхнего
регистра приводит к провалу валидации.
Проверка ориентируется на Unicode-строки и использует встроенные механизмы сравнения регистра, а не только ASCII-диапазон.
import { IsLowercase } from 'class-validator';
export class CreateUserDto {
@IsLowercase()
username: string;
}
В этом случае допустимыми значениями будут:
johnuser123api_keyНедопустимые значения:
JohnUSERtestValue@IsLowercase() не преобразует строку, а только проверяет
её содержимое. Это важный принцип: библиотека не модифицирует
данные.
// НЕ происходит преобразования:
value = value.toLowerCase(); // такого поведения нет
Цифры, символы пунктуации и спецсимволы не влияют на результат проверки:
user_123 — валидноapi-key — валидноtoken.v1 — валидноПроверка касается только буквенных символов.
Валидация учитывает Unicode, поэтому работает не только с латиницей:
москва — валидноberlin — валидно東京 — валидно (в языках без регистра проверка
фактически нейтральна)Важно учитывать, что в языках без различия регистра результат всегда будет успешным, поскольку верхнего/нижнего регистра не существует как категории.
Декоратор @IsUppercase() выполняет обратную задачу —
гарантирует, что все буквенные символы строки находятся в верхнем
регистре.
import { IsUppercase } from 'class-validator';
export class ApiKeyDto {
@IsUppercase()
apiKey: string;
}
Примеры допустимых значений:
ABCUSER_123TOKEN-V1Недопустимые значения:
AbctokenApiKEYКак и в случае с @IsLowercase(), цифры и спецсимволы
игнорируются:
JWT_TOKEN_2024 — валидноAPI-V2-KEY — валидноSERVER_1 — валидноПроверка затрагивает только буквы.
Регистрозависимые системы письма (латиница, кириллица, греческий алфавит) поддерживаются полностью:
МОСКВА — валидноPARIS — валидноΑΘΗΝΑ — валидноОднако в языках без регистра (китайский, японский, корейский слоговый/логографический набор) результат всегда будет успешным, так как сравнение регистра неприменимо.
Оба декоратора часто применяются для обеспечения предсказуемого формата данных на уровне API.
import { IsUppercase, IsLowercase, Length } from 'class-validator';
export class RegisterDto {
@IsLowercase()
username: string;
@IsUppercase()
countryCode: string;
@Length(8, 32)
password: string;
}
Здесь реализуется строгая схема:
username всегда приводится к нижнему регистру до
сохранения или уже приходит в нормализованном видеcountryCode фиксируется в стандарте ISO (например,
US, DE, KZ)password не зависит от регистра, но проверяется по
длине"" — считается валидной строкой для обоих декораторов,
если не применены дополнительные ограничения
(@IsNotEmpty())По умолчанию оба декоратора не валидируют null и
undefined, если не включены дополнительные ограничения:
import { IsOptional, IsUppercase } from 'class-validator';
class ExampleDto {
@IsOptional()
@IsUppercase()
code?: string;
}
import { IsLowercase, Length } from 'class-validator';
class UserDto {
@IsLowercase()
@Length(3, 20)
nickname: string;
}
Здесь порядок декораторов не влияет на результат, так как каждый выполняется независимо.
import { Matches, IsUppercase } from 'class-validator';
class TokenDto {
@IsUppercase()
@Matches(/^[A-Z0-9-]+$/)
token: string;
}
Такое сочетание часто избыточно, но применяется, когда требуется усиленный контроль формата.
По умолчанию библиотека возвращает стандартные сообщения:
is lowercaseis uppercaseЭти сообщения могут быть переопределены:
import { IsUppercase } from 'class-validator';
class Dto {
@IsUppercase({ message: 'Код должен быть в верхнем регистре' })
code: string;
}
В системах, где входные данные проходят через трансформацию
(например, через class-transformer), важно понимать,
что:
@IsLowercase() и @IsUppercase() не
выполняют преобразованиеЭто означает, что любые изменения регистра должны происходить отдельно от валидации.
@IsUppercase()
name: string;
Ожидание: "test" станет "TEST"
Факт: значение не изменяется, только проверяется
@IsUppercase() не подходит для структурированных данных
вроде JSON или email:
USER@MAIL.COM — технически валидно по регистру, но не
является валидным email без дополнительной проверки{TOKEN} — формально проходит проверку регистра, но не
является полезным идентификаторомИспользование этих декораторов должно соответствовать контексту:
@IsUppercase()@IsLowercase()Использование @IsLowercase() и
@IsUppercase() часто является частью стратегии нормализации
данных на уровне входных DTO. Это позволяет:
В больших системах такие проверки становятся частью контракта API, а не просто вспомогательной валидацией.
Проверка регистра в class-validator выполняется синхронно и имеет минимальную стоимость:
На практике это делает декораторы подходящими для массовой валидации больших объектов без заметного влияния на производительность.
import { ValidateNested, IsUppercase } from 'class-validator';
class ItemDto {
@IsUppercase()
code: string;
}
class ContainerDto {
@ValidateNested({ each: true })
items: ItemDto[];
}
В этом случае каждый элемент массива проходит независимую проверку, включая регистровые ограничения.
@IsLowercase() и @IsUppercase() часто
выступают не просто как валидаторы, а как декларативные ограничения
модели данных. Они фиксируют соглашения:
Это делает их важным инструментом в системах, где данные проходят через несколько уровней обработки и интеграций.