Targets, factories, and inference
Lifecycle macros accept either a class target or a factory.
| Choose | When |
|---|---|
target | You have a concrete class and want constructor parameter checking. |
factory | You need async setup, an interface result, configuration, or custom construction. |
Class targets
class Service {
constructor(database: Database, logger: Logger) {}
}
const createService = createTransient({
target: Service,
deps: [database, logger],
});
The deps tuple is checked against the constructor parameters.
Factories
Use a factory for interfaces, configuration, conditional construction, or async setup:
const connection = await createSingleton({
factory: async () => connect(process.env.DATABASE_URL),
});
Factory parameters and return values are inferred. An async factory passed to createTransient produces a function returning a promise:
const createSession = createTransient({
factory: async (database: Database) => database.createSession(),
deps: [database],
});
const session = await createSession();
Pass deps in the same order as the target constructor or factory parameters.
Prefer inference from the target or factory. Add explicit generic arguments only when you need to narrow the public interface or declare a context-key type.