Внедрение через конструктор
Корректно внедряйте зависимости через конструкторы
«Внедрение через конструктор» — бесплатный урок TypeScript Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения TypeScript Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс TypeScript Academy содержит 4 уроков всего.
Подробно о внедрении через конструктор
Внедрение через конструктор объявляет каждую зависимость параметром конструктора. Объект полностью связывается в момент создания, поэтому обязательные зависимости невозможно забыть.
Свойства параметров
TypeScript позволяет за один шаг объявить и присвоить зависимость, используя модификатор доступа параметра. private readonly автоматически создаёт поле и присваивает ему значение.
interface Mailer { send(to: string, body: string): void; }
class Notifier {
constructor(private readonly mailer: Mailer) {}
}Зависимости на основе интерфейсов
Зависимость от интерфейса, а не от класса, отделяет потребителя от конкретной реализации. Можно передать любой объект, соответствующий интерфейсу.
interface Mailer { send(to: string, body: string): void; }
class SmtpMailer implements Mailer {
send(to: string, body: string) { console.log("SMTP ->", to); }
}Связывание в корне композиции
Место, где создаётся граф объектов, называется корнем композиции. Там Вы выбираете конкретные реализации и внедряете их.
class Notifier {
constructor(private readonly mailer: Mailer) {}
notify(to: string) { this.mailer.send(to, "hello"); }
}
const app = new Notifier(new SmtpMailer());
app.notify("a@b.com");Замена реализаций
Поскольку зависимость представлена интерфейсом, можно передать совершенно другую реализацию, не изменяя Notifier. В этом и заключается основная гибкость, которую предоставляет DI.
class FakeMailer implements Mailer {
sent: string[] = [];
send(to: string) { this.sent.push(to); }
}
const fake = new FakeMailer();
new Notifier(fake).notify("x@y.com");
console.log(fake.sent); // ["x@y.com"]Тестирование без реального ввода-вывода
Внедрение fake-почтового сервиса позволяет тесту проверить, что было бы отправлено, без отправки настоящего письма. Тест выполняется быстро, детерминированно и изолированно.
const fake = new FakeMailer();
new Notifier(fake).notify("test@site");
console.log(fake.sent.length === 1); // trueНесколько зависимостей
Указывайте столько зависимостей, сколько необходимо. Каждая из них явная, типизированная и обязательная, поэтому потребности класса сразу видны.
interface Logger { log(m: string): void; }
class Notifier {
constructor(
private readonly mailer: Mailer,
private readonly logger: Logger,
) {}
}readonly предотвращает переназначение
Объявление внедрённых полей как readonly не позволяет заменить их в течение жизненного цикла объекта, сохраняя его зависимости стабильными и предсказуемыми.
class Notifier {
constructor(private readonly mailer: Mailer) {}
// this.mailer = ... would be a compile error
}Без скрытого создания внутри
Класс, использующий внедрение через конструктор, не должен создавать свои зависимости внутри. Все зависимости поступают через конструктор, поэтому связанность остаётся явной.
Обязательные и необязательные зависимости
Обязательные зависимости следует помещать в конструктор. Действительно необязательные зависимости могут по умолчанию использовать реализацию без действий, которая всё равно передаётся извне, а не создаётся внутри.
const noopLogger: Logger = { log() {} };
new Notifier(new SmtpMailer(), noopLogger);Итоги преимуществ
Внедрение через конструктор делает зависимости явными, объекты полностью инициализированными, реализации взаимозаменяемыми, а тесты — простыми. Не зря это основной стиль DI.
Краткая проверка
Краткая проверка по этому уроку.
Итоги
Внедрение через конструктор объявляет зависимости как параметры, часто с модификатором private readonly, и типизирует их интерфейсом. Корень композиции выбирает реализации, а тесты передают подставные реализации. Объекты всегда полностью связаны, а зависимости можно заменять без изменения класса.
Изучай TypeScript с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 101
- Уроки
- 352
Часто задаваемые вопросы
Урок «Внедрение через конструктор» бесплатный?
Да — полный текст урока «Внедрение через конструктор» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс TypeScript Academy, подпишись на CoddyKit PRO. Курс TypeScript Academy содержит 4 уроков всего.
Чему я научусь в уроке «Внедрение через конструктор»?
Корректно внедряйте зависимости через конструкторы Ты практикуешь TypeScript Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать TypeScript Academy?
Предыдущий опыт не требуется. TypeScript Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.
Сколько времени занимает урок «Внедрение через конструктор»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке TypeScript Academy?
Да. Каждый урок TypeScript Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Основы инверсии управления
- Внедрение через конструктор
- DI-контейнеры с InversifyJS
- Типобезопасные токены служб