typestar

Dependency injection by type in TypeScript

Depend on an interface; the caller supplies whatever satisfies it.

interface Clock {
  now(): number;
}

interface Store {
  save(lang: string, tpm: number): Promise<void>;
}

interface Deps {
  clock: Clock;
  store: Store;
}

function makeRecorder({ clock, store }: Deps) {
  return async function record(lang: string, tpm: number): Promise<string> {
    await store.save(lang, tpm);
    return `${lang} at ${tpm} (${clock.now()})`;
  };
}

const calls: string[] = [];
const record = makeRecorder({
  clock: { now: () => 1234 },
  store: { save: async (lang, tpm) => void calls.push(`${lang}:${tpm}`) },
});

record("ts", 98).then((line) => console.log(line, calls));

How it works

  1. The interface is the contract, and it stays small.
  2. A test passes a fake with no framework involved.
  3. Partial application is enough: no container needed.

Keywords and builtins used here

The run, in numbers

Lines
27
Characters to type
578
Tokens
188
Three-star pace
110 tpm

At the three-star pace of 110 tokens a minute, this run takes about 103 seconds.

Type this snippet

Step 2 of 5 in Building & injecting, step 10 of 19 in Classes & patterns.

← Previous Next →