Skip to content

Scopes & Lifetime

A class's scope (set on @Injectable) controls how long its instance lives and whether it is shared.

ScopeBehavior
transientA new instance is built on every inject call. The default.
singletonThe instance is built once, cached on the class, and reused.

Transient (default)

Without a scope, every resolution constructs a fresh instance:

ts
@Injectable()
class RequestContext {}

inject(RequestContext) === inject(RequestContext); // false

Use transient for short-lived, per-use objects that should not share state.

Singleton

A singleton is constructed on first resolution and cached on the class; later inject calls return the same instance:

ts
@Injectable({ scope: 'singleton' })
class Config {}

inject(Config) === inject(Config); // true

Use singleton for shared services - configuration, connection pools, caches.

How the cache works

The cached singleton is stored on the class itself (via a private symbol), not in a shared module-level map. There is no global container to reset, and the cache is scoped to exactly that class - a subclass does not inherit it.

Resetting a singleton

forceInject drops the cached instance and builds a fresh one, which becomes the new cached singleton:

ts
import { inject, forceInject } from '@remotex-labs/xinject';

const first = inject(Config);
const fresh = forceInject(Config);

inject(Config) === fresh; // true - the cache now holds the fresh instance

This is handy between tests, or after configuration changes that should rebuild a shared service.

Released under the Mozilla Public License 2.0