Декоратор @IsArray из библиотеки
class-validator используется для проверки того, что
значение свойства является массивом. Он относится к базовым валидаторам
структуры данных и часто применяется в DTO-объектах, где требуется
строгая типизация входных данных.
Основная задача @IsArray — убедиться, что проверяемое
значение имеет тип Array.
Проверка выполняется строго:
[] — валидно[1, 2, 3] — валидно['a', 'b'] — валидно"text" — невалидно{} — невалидноnull — невалидно (если не указано nullable
поведение через другие декораторы)Важно понимать, что проверка не углубляется в содержимое массива. Она не анализирует тип элементов — только сам факт, что значение является массивом.
Типичный сценарий применения — DTO-классы в связке с
class-validator и class-transformer.
import { IsArray } from 'class-validator';
export class CreateUserDto {
@IsArray()
roles: string[];
}
В этом примере свойство roles должно быть массивом.
Любое другое значение приведёт к ошибке валидации.
В JavaScript и TypeScript данные, поступающие извне (например, из HTTP-запроса), часто приходят в виде строк.
Пример проблемного случая:
{
"roles": "admin"
}
Без преобразования class-validator увидит строку и
отклонит её, так как строка не является массивом.
@IsArray не выполняет преобразование типов. Для
корректной работы с входными данными часто используется
class-transformer.
import { Type } from 'class-transformer';
import { IsArray } from 'class-validator';
export class CreateUserDto {
@IsArray()
@Type(() => String)
roles: string[];
}
Здесь:
@Type(() => String) пытается привести элементы к
строкам@IsArray() проверяет, что значение является
массивом@IsArray не проверяет содержимое, поэтому для сложных
структур требуется комбинирование с другими валидаторами.
import { IsArray, ValidateNested } from 'class-validator';
import { Type } from 'class-transformer';
class PermissionDto {
name: string;
}
export class CreateRoleDto {
@IsArray()
@ValidateNested({ each: true })
@Type(() => PermissionDto)
permissions: PermissionDto[];
}
Здесь:
@IsArray() проверяет, что permissions —
массив@ValidateNested({ each: true }) валидирует каждый
элемент массива@Type() обеспечивает корректную трансформацию
объектовХотя сам @IsArray не принимает параметр
each, он часто используется вместе с другими декораторами,
которые его поддерживают.
Пример:
import { IsArray, IsString } from 'class-validator';
export class CreateDto {
@IsArray()
@IsString({ each: true })
tags: string[];
}
Здесь:
@IsArray() проверяет структуру@IsString({ each: true }) проверяет каждый элемент
массиваПроблема:
roles: "admin,user"
Ожидание: массив Фактически: строка
Решение: использовать @Type(() => ...) или
предварительно парсить данные.
roles: { 0: 'admin', 1: 'user' }
Это объект, а не массив, даже если структура похожа.
@IsArray()
permissions: any[];
Без @ValidateNested содержимое массива остаётся
невалидированным.
Пустой массив считается валидным значением:
roles: []
@IsArray не требует наличия элементов.
Если необходимо запрещать пустые массивы, используется дополнительный декоратор:
import { ArrayNotEmpty, IsArray } from 'class-validator';
@IsArray()
@ArrayNotEmpty()
roles: string[];
@IsArray редко используется изолированно. На практике он
комбинируется:
@ArrayMinSize, @ArrayMaxSize@ArrayNotEmpty@IsString({ each: true })@ValidateNested({ each: true })Пример комплексной валидации:
import {
IsArray,
ArrayMinSize,
ArrayMaxSize,
IsInt,
} from 'class-validator';
export class NumbersDto {
@IsArray()
@ArrayMinSize(2)
@ArrayMaxSize(5)
@IsInt({ each: true })
values: number[];
}
TypeScript-типизация не заменяет runtime-валидацию.
roles: string[];
Даже если тип указан как string[], во время выполнения
значение может быть любым. Именно поэтому @IsArray
критически важен в API-слое.
@IsArray одинаково работает для любых массивов:
Однако смешанные типы усложняют последующую обработку и обычно считаются антипаттерном в DTO-структурах.
export class UpdateUserDto {
@IsArray()
roles: string[];
@IsArray()
permissions: string[];
}
Используется аналогично для входных объектов мутаций.
export class AppConfig {
@IsArray()
allowedOrigins: string[];
}
@IsArray не пропускает null и
undefined по умолчанию.
Для разрешения отсутствующих значений используется:
import { IsArray, IsOptional } from 'class-validator';
@IsOptional()
@IsArray()
roles: string[];
При расширении классов валидация сохраняется:
class BaseDto {
@IsArray()
roles: string[];
}
class ExtendedDto extends BaseDto {
additional: string;
}
@IsArray выполняет единственную операцию:
Array.isArray(value) === trueВсе остальные аспекты — длина, содержимое, типы элементов — выносятся в дополнительные декораторы.