0Pricing
TypeScript Academy · Lesson

Constructor Injection

Inject dependencies through constructors cleanly.

Constructor Injection is a free TypeScript Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the TypeScript Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Constructor Injection in Depth

Constructor injection declares every dependency as a constructor parameter. The object is fully wired the moment it exists, which makes required collaborators impossible to forget.

Parameter Properties

TypeScript can declare and assign a dependency in one step using an access modifier on the parameter. private readonly creates and assigns the field automatically.

interface Mailer { send(to: string, body: string): void; }
class Notifier {
  constructor(private readonly mailer: Mailer) {}
}

Interface-Based Dependencies

Depending on an interface rather than a class decouples the consumer from any specific implementation. Any object matching the interface can be supplied.

interface Mailer { send(to: string, body: string): void; }
class SmtpMailer implements Mailer {
  send(to: string, body: string) { console.log("SMTP ->", to); }
}

Wiring at the Composition Root

The place that creates the object graph is the composition root. There you pick concrete implementations and inject them.

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");

Swapping Implementations

Because the dependency is an interface, you can supply a totally different implementation without touching Notifier. This is the core flexibility DI provides.

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"]

Testing Without Real I/O

Injecting the fake mailer lets a test assert what would have been sent, with no real email. The test is fast, deterministic, and isolated.

const fake = new FakeMailer();
new Notifier(fake).notify("test@site");
console.log(fake.sent.length === 1); // true

Multiple Dependencies

List as many dependencies as needed. Each is explicit, typed, and required, which keeps the class's needs visible at a glance.

interface Logger { log(m: string): void; }
class Notifier {
  constructor(
    private readonly mailer: Mailer,
    private readonly logger: Logger,
  ) {}
}

readonly Prevents Reassignment

Marking injected fields readonly stops them from being swapped mid-life, keeping the object's collaborators stable and predictable.

class Notifier {
  constructor(private readonly mailer: Mailer) {}
  // this.mailer = ... would be a compile error
}

No Hidden new Inside

A class using constructor injection should not new up its collaborators internally. All dependencies arrive through the constructor, keeping coupling explicit.

Required vs Optional

Required dependencies belong in the constructor. Truly optional ones can default to a no-op implementation, still passed in rather than constructed inside.

const noopLogger: Logger = { log() {} };
new Notifier(new SmtpMailer(), noopLogger);

Benefits Summary

Constructor injection makes dependencies explicit, objects fully initialized, implementations swappable, and tests trivial. It is the default DI style for good reason.

Quick Check

Quick check on this lesson.

Recap

Constructor injection declares dependencies as parameters (often private readonly) typed by interface. The composition root picks implementations; tests pass fakes. Objects are always fully wired, and collaborators are swappable without editing the class.

Frequently asked questions

Is the “Constructor Injection” lesson free?

Yes — the full text of “Constructor Injection” is free to read here on the web, and the TypeScript Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the TypeScript Academy course, upgrade to CoddyKit PRO.

What will I learn in “Constructor Injection”?

Inject dependencies through constructors cleanly. You practise TypeScript Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start TypeScript Academy?

No prior experience is required. TypeScript Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Constructor Injection” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this TypeScript Academy lesson?

Yes. Every TypeScript Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Inversion of Control Basics
  2. Constructor Injection
  3. DI Containers with InversifyJS
  4. Type-Safe Service Tokens
← Back to TypeScript Academy