Ответ
Нет, декораторы в TypeScript (и экспериментальные декораторы в JavaScript) могут применяться к нескольким типам объявлений. В моих Node.js проектах с TypeScript я использую декораторы для:
1. Декораторы классов — для регистрации в DI-контейнере, добавления метаданных:
import { Injectable, Singleton } from 'tsyringe';
@Injectable() // Декоратор класса
@Singleton() // Можно применять несколько декораторов
class DatabaseService {
constructor(private config: ConfigService) {}
async connect() {
return await mongoose.connect(this.config.databaseUrl);
}
}
2. Декораторы методов — для логирования, кэширования, валидации:
import { Get, Controller, UseGuards } from '@nestjs/common';
@Controller('users')
class UsersController {
@Get() // Декоратор метода HTTP
@UseGuards(AuthGuard) // Декоратор middleware
@CacheTTL(60) // Декоратор кэширования
async getAllUsers() {
return await this.userService.findAll();
}
}
3. Декораторы свойств — для валидации, сериализации, внедрения зависимостей:
import { Expose, Type } from 'class-transformer';
import { IsEmail, IsString } from 'class-validator';
class UserDto {
@Expose() // Декоратор свойства для class-transformer
id: number;
@IsString() // Валидация
@IsEmail() // Можно несколько декораторов
email: string;
@Type(() => Date) // Преобразование типа
createdAt: Date;
}
4. Декораторы параметров — для внедрения зависимостей в параметры конструктора/методов:
import { Inject } from '@nestjs/common';
class UserService {
constructor(
@Inject('USER_MODEL') // Декоратор параметра
private userModel: Model<User>,
@Inject(ConfigService)
private config: ConfigService
) {}
}
5. Декораторы аксессоров (геттеров/сеттеров):
class Product {
private _price: number;
@Min(0) // Декоратор аксессора
get price() {
return this._price;
}
set price(value: number) {
this._price = value;
}
}
В Node.js с TypeScript декораторы полностью поддерживаются с флагом experimentalDecorators: true в tsconfig.json. В чистом JavaScript (Node.js ≥ 14) можно использовать экспериментальные декораторы с флагом --experimental-decorators, но TypeScript предлагает более стабильную и богатую реализацию.
Практический пример из моего опыта — декоратор для логирования времени выполнения методов:
function LogExecutionTime() {
return function (
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
) {
const originalMethod = descriptor.value;
descriptor.value = async function (...args: any[]) {
const start = Date.now();
const result = await originalMethod.apply(this, args);
const duration = Date.now() - start;
console.log(`${propertyKey} executed in ${duration}ms`);
return result;
};
return descriptor;
};
}
class UserService {
@LogExecutionTime()
async findUsers() {
// Длительная операция
return await db.users.findMany();
}
}