class-transformer для TypeScript: полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение в class-transformer: что это и зачем нужно

class-transformer — это мощная библиотека для TypeScript и JavaScript, которая позволяет преобразовывать обычные (plain) объекты JavaScript в экземпляры классов и обратно. Она решает фундаментальную проблему: при работе с данными из API, баз данных или JSON-файлов вы получаете простые объекты без методов и типов. class-transformer «оживляет» эти данные, превращая их в полноценные объекты классов с валидацией, трансформацией и сериализацией.

Основные сценарии использования:

  • Преобразование JSON из API в типизированные объекты классов — например, после получения ответа от REST API вы можете автоматически преобразовать JSON в экземпляры ваших моделей.
  • Валидация и трансформация данных — с помощью декораторов можно указать, какие поля обязательны, какие нужно преобразовать (например, строку в число или дату).
  • Сериализация объектов в JSON — обратное преобразование экземпляров классов в простые объекты для отправки на клиент или сохранения.
  • Работа с вложенными объектами и массивами — библиотека умеет рекурсивно преобразовывать вложенные структуры данных.

class-transformer часто используется вместе с class-validator (для валидации) и популярными фреймворками, такими как NestJS, TypeORM и MikroORM.

Установка

Установка библиотеки производится через npm или yarn:

npm install class-transformer --save

Или, если вы используете yarn:

yarn add class-transformer

Для работы с декораторами в TypeScript необходимо включить поддержку экспериментальных декораторов в файле tsconfig.json:

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

Также рекомендуется установить reflect-metadata для корректной работы декораторов:

npm install reflect-metadata --save

И импортировать его в самом начале вашего приложения (обычно в главном файле index.ts или main.ts):

import 'reflect-metadata';

Быстрый старт с примером кода

Давайте создадим простую модель пользователя и преобразуем JSON-данные в экземпляр класса.

import { plainToClass, Expose, Type } from 'class-transformer';
import 'reflect-metadata';

// Определяем класс User
class User {
    @Expose()
    id: number;

    @Expose()
    firstName: string;

    @Expose()
    lastName: string;

    @Expose()
    @Type(() => Date)
    createdAt: Date;

    // Метод класса — доступен только после трансформации
    getFullName(): string {
        return `${this.firstName} ${this.lastName}`;
    }
}

// Пример данных из API (plain object)
const plainUser = {
    id: 1,
    firstName: 'Иван',
    lastName: 'Петров',
    createdAt: '2024-01-15T10:30:00Z'
};

// Преобразуем plain object в экземпляр класса User
const userInstance = plainToClass(User, plainUser);

console.log(userInstance instanceof User); // true
console.log(userInstance.getFullName());   // "Иван Петров"
console.log(userInstance.createdAt);       // Date object: Tue Jan 15 2024 13:30:00 GMT+0300

Как видите, мы получили полноценный объект класса с методами и правильно преобразованными типами (строка даты стала объектом Date).

Основные методы и функции class-transformer

1. plainToClass

Что делает: Преобразует один или несколько простых (plain) объектов в экземпляры указанного класса. Это самый часто используемый метод.

Параметры:

  • cls: new (...args: any[]) => T — конструктор класса, в который нужно преобразовать.
  • plain: T[] | T — простой объект или массив объектов.
  • options?: ClassTransformOptions — необязательные опции (например, excludeExtraneousValues, enableCircularCheck).

Пример:

import { plainToClass } from 'class-transformer';

class Product {
    id: number;
    name: string;
    price: number;
}

const plainProduct = { id: 1, name: 'Ноутбук', price: 75000 };
const product = plainToClass(Product, plainProduct);
console.log(product instanceof Product); // true

2. classToPlain

Что делает: Обратное преобразование — из экземпляра класса в простой объект (plain object). Полезно для сериализации перед отправкой на клиент.

Параметры:

  • object: T — экземпляр класса.
  • options?: ClassTransformOptions — опции трансформации.

Пример:

import { classToPlain } from 'class-transformer';

const productInstance = new Product();
productInstance.id = 1;
productInstance.name = 'Монитор';
productInstance.price = 25000;

const plain = classToPlain(productInstance);
console.log(plain); // { id: 1, name: 'Монитор', price: 25000 }
console.log(plain instanceof Product); // false

3. serialize

Что делает: Сериализует экземпляр класса (или массив экземпляров) в JSON-строку. По сути, это комбинация classToPlain и JSON.stringify.

Параметры:

  • object: T | T[] — экземпляр класса или массив.
  • options?: ClassTransformOptions — опции.

Пример:

import { serialize } from 'class-transformer';

const jsonString = serialize(productInstance);
console.log(jsonString); // '{"id":1,"name":"Монитор","price":25000}'

4. deserialize

Что делает: Десериализует JSON-строку в экземпляр класса. Обратная операция к serialize.

Параметры:

  • cls: new (...args: any[]) => T — класс.
  • json: string — JSON-строка.
  • options?: ClassTransformOptions — опции.

Пример:

import { deserialize } from 'class-transformer';

const json = '{"id":2,"name":"Клавиатура","price":5000}';
const keyboard = deserialize(Product, json);
console.log(keyboard instanceof Product); // true
console.log(keyboard.name); // "Клавиатура"

5. plainToClassFromExist

Что делает: Преобразует plain-объект в существующий экземпляр класса (обновляет его поля). Полезно для частичного обновления данных.

Параметры:

  • cls: new (...args: any[]) => T — класс.
  • plain: T[] | T — данные для обновления.
  • existingObject: T — существующий экземпляр.
  • options?: ClassTransformOptions — опции.

Пример:

import { plainToClassFromExist } from 'class-transformer';

const existingProduct = new Product();
existingProduct.id = 1;
existingProduct.name = 'Старое название';
existingProduct.price = 100;

const updateData = { name: 'Новое название', price: 200 };
plainToClassFromExist(Product, updateData, existingProduct);
console.log(existingProduct.name); // "Новое название"
console.log(existingProduct.id);   // 1 (не изменилось)

6. instanceToPlain

Что делает: Аналог classToPlain, но с улучшенной поддержкой вложенных объектов и массивов. Рекомендуется использовать вместо classToPlain в новых проектах.

Параметры:

  • object: T | T[] — экземпляр класса.
  • options?: ClassTransformOptions — опции.

Пример:

import { instanceToPlain } from 'class-transformer';

const plainFromInstance = instanceToPlain(productInstance);

7. instanceToInstance

Что делает: Клонирует экземпляр класса с применением всех трансформаций. Создает новый объект того же класса.

Параметры:

  • object: T — исходный экземпляр.
  • options?: ClassTransformOptions — опции.

Пример:

import { instanceToInstance } from 'class-transformer';

const clonedProduct = instanceToInstance(productInstance);
console.log(clonedProduct instanceof Product); // true
console.log(clonedProduct !== productInstance); // true (разные объекты)

8. @Expose()

Что делает: Декоратор, который указывает, что поле должно быть включено в процесс трансформации. По умолчанию все поля класса участвуют, но с помощью опций можно управлять этим.

Параметры:

  • options?: ExposeOptions — может содержать name (для маппинга на другое имя в JSON), groups и другие.

Пример:

import { Expose } from 'class-transformer';

class User {
    @Expose({ name: 'user_id' })
    id: number;

    @Expose()
    name: string;
}

const plain = { user_id: 1, name: 'Анна' };
const user = plainToClass(User, plain);
console.log(user.id); // 1 (поле id получило значение из user_id)

9. @Exclude()

Что делает: Декоратор, исключающий поле из процесса трансформации. Полезно для скрытия паролей или внутренних данных.

Параметры:

  • options?: ExcludeOptions — может содержать toClassOnly или toPlainOnly для выборочного исключения.

Пример:

import { Exclude, Expose } from 'class-transformer';

class User {
    @Expose()
    username: string;

    @Exclude()
    password: string;
}

const user = new User();
user.username = 'ivan';
user.password = 'secret123';

const plain = classToPlain(user);
console.log(plain); // { username: 'ivan' } — password исключен

10. @Transform()

Что делает: Декоратор для кастомной трансформации поля. Позволяет применить произвольную функцию преобразования.

Параметры:

  • transformFn: (params: TransformFnParams) => any — функция трансформации.
  • options?: TransformOptions — опции (например, groups).

Пример:

import { Transform } from 'class-transformer';

class Product {
    @Transform(({ value }) => value.toUpperCase())
    name: string;

    @Transform(({ value }) => Math.round(value))
    price: number;
}

const plain = { name: 'ноутбук', price: 74999.99 };
const product = plainToClass(Product, plain);                    

Рекомендаций