← Назад к вопросам

Какие знаешь DI декораторы?

1.7 Middle🔥 111 комментариев
#Soft Skills и рабочие процессы

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI4 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

DI-декораторы в современном JavaScript/TypeScript

В контексте фронтенд-разработки DI (Dependency Injection — внедрение зависимостей) декораторы чаще всего ассоциируются с фреймворками Angular и библиотеками, поддерживающими декораторы TypeScript. Вот основные из них:

Основные декораторы Angular

1. @Injectable()

Маркирует класс как сервис, который может быть внедрен через DI-контейнер Angular.

@Injectable({
  providedIn: 'root' // или 'platform', 'any', либо в конкретном модуле
})
export class UserService {
  private users: User[] = [];

  getUsers(): User[] {
    return this.users;
  }
}

Ключевые особенности:

  • providedIn: определяет область видимости сервиса
  • root: singleton на уровне приложения
  • platform: singleton на уровне платформы
  • any: отдельный экземпляр для каждого внедряющего модуля

2. @Inject()

Позволяет внедрять зависимости, которые не являются классами (примитивы, интерфейсы, готовые объекты).

export class ApiService {
  constructor(
    @Inject('API_URL') private apiUrl: string,
    @Inject(HttpClient) private http: HttpClient
  ) {}

  getUsers() {
    return this.http.get(`${this.apiUrl}/users`);
  }
}

Использование в провайдере:

providers: [
  { provide: 'API_URL', useValue: 'https://api.example.com' }
]

3. Опциональные зависимости с @Optional()

Указывает, что зависимость может отсутствовать.

export class LoggerService {
  constructor(@Optional() @Inject('LOG_LEVEL') private logLevel?: string) {
    this.logLevel = logLevel || 'info';
  }
}

4. @Self(), @SkipSelf(), @Host()

Декораторы для управления поиском зависимостей в иерархии инжекторов:

  • @Self(): искать только в собственном инжекторе компонента
  • @SkipSelf(): пропустить собственный инжектор, начать с родительского
  • @Host(): остановить поиск на инжекторе текущего хоста
export class ChildComponent {
  constructor(
    @Self() private localService: LocalService,
    @SkipSelf() private parentService: ParentService,
    @Host() private hostService: HostService
  ) {}
}

Декораторы для внедрения в компоненты и директивы

5. @Component() и @Directive()

Хотя это не чисто DI-декораторы, они предоставляют метаданные для DI через свойство providers:

@Component({
  selector: 'app-user-list',
  templateUrl: './user-list.component.html',
  providers: [UserService] // Сервис будет доступен только в этом компоненте и его потомках
})
export class UserListComponent {
  constructor(private userService: UserService) {}
}

Расширенные паттерны DI

Кастомные декораторы для DI

Можно создавать собственные декораторы для автоматического внедрения:

export function InjectConfig(configKey: string) {
  return function(target: any, propertyKey: string, parameterIndex: number) {
    const configToken = `${configKey}_CONFIG`;
    
    // Регистрируем параметр для внедрения
    const injectParams = Reflect.getOwnMetadata('design:paramtypes', target) || [];
    injectParams[parameterIndex] = { token: configToken };
    Reflect.defineMetadata('design:paramtypes', injectParams, target);
  };
}

// Использование
export class ConfigService {
  constructor(@InjectConfig('api') private apiConfig: any) {}
}

DI в других фреймворках и библиотеках

InversifyJS

Библиотека для инверсии управления с поддержкой декораторов:

import { injectable, inject } from 'inversify';

@injectable()
class UserService {
  constructor(@inject('Logger') private logger: ILogger) {}
}

TypeDI

Еще одна популярная библиотека для DI:

import { Service, Inject } from 'typedi';

@Service()
class UserService {
  constructor(@Inject() private logger: LoggerService) {}
}

Практические аспекты использования DI декораторов

Преимущества:

  • Тестируемость: легко заменять реальные зависимости моками
  • Гибкость: изменение реализации без изменения клиентского кода
  • Модульность: четкое разделение ответственности
  • Управление жизненным циклом: контроль над созданием и уничтожением объектов

Рекомендации по использованию:

  1. Используйте интерфейсы для абстракции зависимостей
  2. Избегайте циклических зависимостей
  3. Используйте иерархию инжекторов для управления областью видимости сервисов
  4. Минимизируйте использование глобальных сервисов (providedIn: 'root')

Современные тенденции

С появлением Angular 14+ появилась возможность использовать inject() функцию как альтернативу декораторам в конструкторе:

export class UserService {
  private http = inject(HttpClient);
  private apiUrl = inject('API_URL');
}

Этот подход особенно полезен:

  • В функциях инициализации
  • В хуках жизненного цикла
  • В случаях, когда декораторы конструктора неудобны

DI декораторы остаются мощным инструментом для создания масштабируемых, поддерживаемых и тестируемых фронтенд-приложений, особенно в крупных проектах с четкой архитектурой.

Какие знаешь DI декораторы? | PrepBro