inject & forceInject
inject
inject(token, ...args) resolves and constructs a class registered with @Injectable. It:
- Returns the cached instance if the class is a resolved
singleton. - Reads the class's registration - throwing if it was never decorated.
- Resolves each
@Injectparameter from the class'sprovidersregistry. - Constructs the class (or calls its
factory), caching the result when the scope issingleton.
import { inject, Injectable } from '@remotex-labs/xinject';
@Injectable()
class Service {}
const instance = inject(Service); // instanceof ServiceInjecting dependencies
Each constructor parameter declares its dependency with @Inject:
@Injectable()
class Database {}
@Injectable()
class UserService {
constructor(@Inject(Database) public db: Database) {}
}
inject(UserService).db; // a Database instanceOverriding arguments
Arguments passed to inject fill undecorated parameters and take precedence over the @Inject token at each position:
@Injectable()
class Logger {}
@Injectable()
class Service {
constructor(@Inject(Logger) public logger: Logger) {}
}
const stub = new Logger();
inject(Service, stub).logger === stub; // trueErrors
inject throws when the class was not registered:
class NotRegistered {}
inject(NotRegistered); // throws: Cannot inject NotRegistered - not marked @InjectableIt also throws when a requested InjectionToken has no provider (No provider for InjectionToken(...)), and when it detects a dependency cycle.
forceInject
forceInject(token, ...args) behaves like inject but first drops any cached singleton for the class, so a fresh instance is always built (and, for a singleton, becomes the new cached instance).
import { inject, forceInject, Injectable } from '@remotex-labs/xinject';
@Injectable({ scope: 'singleton' })
class Service {}
const first = inject(Service);
const fresh = forceInject(Service);
fresh === first; // false - a new instance was built
inject(Service) === fresh; // true - the cache now holds the fresh instanceUse it to reset a singleton's state (for example, between tests, or after a configuration change). It replaces only the target class's cached instance, not those of its dependencies.
Type inference
inject is fully typed: the return type is the instance type of the token, and the variadic args are typed against the constructor's parameters.
@Injectable()
class Api {
constructor(public url: string) {}
}
const api = inject(Api, 'https://example.com'); // api: Api