Skip to content

@Inject

@Inject(token) is a constructor-parameter decorator that tells inject which token to resolve for that parameter. It is the primary way to declare a dependency.

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

@Injectable()
class Logger {}

@Injectable()
class UserService {
    constructor(@Inject(Logger) private logger: Logger) {}
}

inject(UserService); // logger is resolved and passed automatically

How a token resolves

A token can be a class, an abstract class, an InjectionToken, or a plain string / symbol. For each @Inject(token) parameter, inject looks the token up in the class's providers registry:

  • Found - it is resolved through its binding (useValue, useClass, useFactory).
  • Not found, and the token is a class - the class self-injects, so a plain class dependency needs no provider entry.
  • Not found, and the token is anything else (InjectionToken, abstract class, string, symbol) - inject throws No provider for <token>.
ts
const SQL = new InjectionToken<string>('SQL');

@Injectable({ providers: [{ provide: SQL, useValue: 'SELECT * FROM users' }] })
class Database {
    constructor(
        @Inject(Logger) public logger: Logger, // class token -> self-injects
        @Inject(SQL)    public sql: string,     // InjectionToken -> resolved from providers
    ) {}
}

Resolution is by token, not by position, so the order of parameters and of providers entries does not matter.

Overriding with an explicit argument

An argument passed to inject wins over the @Inject token at the same position - useful for tests and one-off overrides:

ts
const stub = new Logger();

inject(UserService, stub).logger === stub; // true

Undecorated parameters

A parameter without @Inject is not resolved from the container. It is filled only by an explicit argument to inject, and is otherwise undefined:

ts
@Injectable()
class Api {
    constructor(public url: string) {} // no @Inject
}

inject(Api, 'https://example.com').url; // 'https://example.com'
inject(Api).url;                         // undefined

For a value dependency you want the container to own, bind it to an InjectionToken and @Inject it instead.

Released under the Mozilla Public License 2.0