Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Dependency Injection pattern for service definitions, factories, and composition roots. Use when working with packages that use the DI pattern.
.claude/skills/trezor-dependency-injection/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | -44% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 16% | 0% |
| case-03 | ✗→✓ | ▲ Improved | -11% | 0% |
| case-05 | ✗→✓ | ▲ Improved | -35% | 0% |
| case-17 | ✗→✓ | ▲ Improved | -59% | 0% |
Some parts of the codebase use the Dependency Injection (DI) pattern. Instead of importing dependencies directly, pass them to the service as parameters. This allows better testability and separation of concerns.
Use this skill mainly for packages that directly mention this skill.
The unified pattern for defining services is as follows.
Define in this order for consistency:
Use the same key (serviceName) everywhere. This is important so Dep, Deps, and composition root wiring stay consistent.
tsexport type ServiceNameDeps = OtherServiceDep | AnotherServiceDep;
tsexport type ServiceParams = { id: string; // ... }; // Usually a function, but it can also be an object with multiple methods. export type ServiceName = (params: ServiceParams) => ServiceResult;
tsexport type ServiceNameDeps = { serviceName: ServiceName; };
Do not repeat ServiceParams in factory ((params) only). It is inferred from ServiceName.
Service factory:
File shall be named: createServiceName.ts.
tsexport const createServiceName = (deps: ServiceNameDeps): ServiceName => params => { // params is inferred from ServiceName type return deps.serviceName(params); };
This is the place where the tree of dependencies is created and wired together.
service factory, but the service in this case is the whole module/package.
Composition root:
ts// Composition root may have its own dependencies type CompositionRootDeps = ADep; export const createCompositionRoot = (deps: CompositionRootDeps) => { const otherService = createOtherService(deps); const serviceName = createServiceName({ otherService }); return { serviceName, // expose only `serviceName`; `otherService` is module-private in this case }; };
useServices accepts multiple selectors. Prefer one call with all needed selectors instead of multiple useServices calls when a component or hook needs several services.
tsconst { serviceName, otherService } = useServices(selectServiceNameDep, selectOtherServiceDep);
Other measured skills in the registry, with their headline benchmark lift.