Skip to main content
Version: Next

Binding Syntax

Binding syntax is provided as a fluent interface resulting from using the container API or the container module API.

BindToFluentSyntax

interface BindToFluentSyntax<T> {
// ...
}

Represents a service binding given a service identifier.

const bindingToSyntax = container.bind('service-id');

Further documentation refers to this service identifier as the "given service identifier".

to

to(type: Newable<T>): BindInWhenOnFluentSyntax<T>;

Binds a class instantiation to the given service binding. Whenever the service is resolved, the class constructor will be invoked to build the resolved value.

const container: Container = new Container();
container.bind<Weapon>('Weapon').to(Katana);

const katana: Weapon = container.get<Weapon>('Weapon');

toSelf

toSelf(): BindInWhenOnFluentSyntax<T>;

If the given service identifier is a class, establish a type binding to that class.

const container: Container = new Container();
container.bind<Weapon>(Katana).toSelf();

const katana: Weapon = container.get<Weapon>(Katana);

toConstantValue

toConstantValue(value: T): BindWhenOnFluentSyntax<T>;

Binds a value in singleton scope to the given service identifier.

const container: Container = new Container();
container.bind<Weapon>('Weapon').toConstantValue(new Katana());

const katana: Weapon = container.get<Weapon>('Weapon');

toDynamicValue

toDynamicValue(builder: DynamicValueBuilder<T>): BindInWhenOnFluentSyntax<T>;

Binds a function to the given service identifier. Whenever the service is resolved, the function passed will be invoked to build the resolved value.

info

Keep in mind a service is not resolved if it's cached in the current scope.

const container: Container = new Container();
container.bind<Weapon>('Weapon').toDynamicValue((): Weapon => new Katana());

const katana: Weapon = container.get<Weapon>('Weapon');

toFactory

toFactory(
factory: T extends Factory<unknown, any>
? (context: ResolutionContext) => T
: never,
): BindWhenOnFluentSyntax<T>;

Binds a factory to the given service identifier. Whenever the service is resolved, the factory will be passed as the resolved value.

container.bind<Engine>('Engine').to(PetrolEngine).whenNamed('petrol');
container.bind<Engine>('Engine').to(DieselEngine).whenNamed('diesel');

container
.bind<Factory<(displacement: number) => Engine, [string]>>('Factory<Engine>')
.toFactory((context: ResolutionContext) => {
return (named: string) => (displacement: number) => {
const engine: Engine = context.get<Engine>('Engine', {
name: named,
});
engine.displacement = displacement;
return engine;
};
});

@injectable()
class DieselCarFactory implements CarFactory {
readonly #dieselFactory: (displacement: number) => Engine;

constructor(
@inject('Factory<Engine>')
factory: (category: string) => (displacement: number) => Engine, // Injecting an engine factory
) {
// Creating a diesel engine factory
this.#dieselFactory = factory('diesel');
}

public createEngine(displacement: number): Engine {
// Creating a concrete diesel engine
return this.#dieselFactory(displacement);
}
}

toProvider

toProvider(
provider: T extends Provider<unknown, any>
? (context: ResolutionContext) => T
: never,
): BindWhenOnFluentSyntax<T>;

Binds a provider of services associated with a target service identifier to the given service identifier. A provider is just an asynchronous factory.

const container: Container = new Container();

interface Sword {
material: string;
damage: number;
}

@injectable()
class Katana implements Sword {
public material!: string;
public damage!: number;
}

type SwordProvider = (material: string, damage: number) => Promise<Sword>;

container.bind<Sword>('Sword').to(Katana);

container
.bind<SwordProvider>('SwordProvider')
.toProvider((context: ResolutionContext) => {
return async (material: string, damage: number): Promise<Sword> => {
// Custom args!
return new Promise<Sword>(
(resolve: (value: Sword | PromiseLike<Sword>) => void) => {
setTimeout(() => {
const katana: Sword = context.get<Sword>('Sword');
katana.material = material;
katana.damage = damage;
resolve(katana);
}, 10);
},
);
};
});

const katanaProvider: SwordProvider =
container.get<SwordProvider>('SwordProvider');

const powerfulGoldKatana: Promise<Sword> = katanaProvider('gold', 100);

const notSoPowerfulGoldKatana: Promise<Sword> = katanaProvider('gold', 10);

toService

toService(service: ServiceIdentifier<T>): void;

Binds the services bound to a target service identifier to the given service identifier.

const container: Container = new Container();

container.bind(lorcanaCardCatalogProviderSymbol).to(LorcanaCardCatalogProvider);
container.bind(mtgCardCatalogProviderSymbol).to(MtgCardCatalogProvider);

container
.bind(cardCatalogProviderSymbol)
.toService(lorcanaCardCatalogProviderSymbol);
container
.bind(cardCatalogProviderSymbol)
.toService(mtgCardCatalogProviderSymbol);

const cardCatalogProviders: CardCatalogProvider<unknown>[] = container.getAll(
cardCatalogProviderSymbol,
);

BindInFluentSyntax

interface BindInFluentSyntax<T> {
// ...
}

Represents a service binding given a service identifier and a service resolution such as a constructor, a factory, or a provider.

inSingletonScope

inSingletonScope(): BindWhenOnFluentSyntax<T>;

Sets the binding scope to singleton. Refer to the docs for more information.

inTransientScope

inTransientScope(): BindWhenOnFluentSyntax<T>;

Sets the binding scope to transient. Refer to the docs for more information.

inRequestScope

inRequestScope(): BindWhenOnFluentSyntax<T>;

Sets the binding scope to request. Refer to the docs for more information.

BindOnFluentSyntax

interface BindOnFluentSyntax<T> {
// ...
}

Allows setting binding activation and deactivation handlers.

onActivation

onActivation(activation: BindingActivation<T>): BindWhenFluentSyntax<T>;

Sets a binding activation handler. The activation handler is invoked after a dependency has been resolved and before it is added to a scope cache. The activation handler will not be invoked if the dependency is taken from a scope cache.

@injectable()
class Katana {
public use(): string {
return 'hit!';
}
}

container
.bind<Katana>('Katana')
.to(Katana)
.onActivation((_context: ResolutionContext, katana: Katana) => {
const handler: ProxyHandler<() => string> = {
apply: function (
target: () => string,
thisArgument: unknown,
argumentsList: [],
) {
console.log(`Starting: ${new Date().getTime().toString()}`);
const result: string = target.apply(thisArgument, argumentsList);
console.log(`Finished: ${new Date().getTime().toString()}`);
return result;
},
};

katana.use = new Proxy(katana.use.bind(katana), handler);

return katana;
});

onDeactivation

onDeactivation(deactivation: BindingDeactivation<T>): BindWhenFluentSyntax<T>;

Sets a binding deactivation handler on a singleton scope binding. The deactivation handler is called when the binding is unbound from a container.

BindWhenFluentSyntax

interface BindWhenFluentSyntax<T> {
// ...
}

Allows setting binding constraints.

when

Sets a constraint for the current binding.

when(
constraint: (metadata: BindingMetadata) => boolean,
): BindOnFluentSyntax<T>;
const ninjaId: symbol = Symbol.for('Ninja');
const weaponId: symbol = Symbol.for('Weapon');

@injectable()
class Ninja {
constructor(
@inject(weaponId)
@named('shuriken')
public readonly weapon: Weapon,
) {}
}

container.bind<Ninja>(ninjaId).to(Ninja);

const whenTargetNamedConstraint: (
name: string,
) => (bindingMetadata: BindingMetadata) => boolean =
(name: string) =>
(bindingMetadata: BindingMetadata): boolean =>
bindingMetadata.name === name;

container
.bind<Weapon>(weaponId)
.to(Katana)
.when(whenTargetNamedConstraint('katana'));

container
.bind<Weapon>(weaponId)
.to(Shuriken)
.when(whenTargetNamedConstraint('shuriken'));

const ninja: Ninja = container.get(ninjaId);

// Returns 5
const ninjaDamage: number = ninja.weapon.damage;

In the previous example, a custom constraint is implemented to use the binding if and only if the target name is a certain one.

whenAnyAncestor

whenAnyAncestor(
constraint: (metadata: BindingMetadata) => boolean,
): BindOnFluentSyntax<T>;

Constrains the binding to be used if and only if, given a constraint, any ancestor service matches the given constraint.

whenAnyAncestorIs

whenAnyAncestorIs(
serviceIdentifier: ServiceIdentifier,
): BindOnFluentSyntax<T>;

Constrains the binding to be used if and only if, given a service identifier, any ancestor service was requested with the given identifier.

whenAnyAncestorNamed

whenAnyAncestorNamed(name: MetadataName): BindOnFluentSyntax<T>;

Constrains the binding to be used if and only if, given a name, a named parent service was requested with the given name.

whenAnyAncestorTagged

whenAnyAncestorTagged(
tag: MetadataTag,
tagValue: unknown,
): BindOnFluentSyntax<T>;

Constrains the binding to be used if and only if, given a tag, a tagged parent service was requested with the given tag.

whenDefault

whenDefault(): BindOnFluentSyntax<T>;

Constrains the binding to be used if and only if the service is not requested with any name nor tags.

whenNamed

Constrains the binding to be used if and only if, given a name, a named service is requested with the given name.

whenNamed(name: MetadataName): BindOnFluentSyntax<T>;

whenNoAncestor

whenNoAncestor(
constraint: (metadata: BindingMetadata) => boolean,
): BindOnFluentSyntax<T>;

Constrains the binding to be used if and only if, given a constraint, no ancestor service matches the given constraint.

whenNoAncestorIs

whenNoAncestorIs(serviceIdentifier: ServiceIdentifier): BindOnFluentSyntax<T>;

Constrains the binding to be used if and only if, given a service identifier, no ancestor service was requested with the given identifier.

whenNoAncestorNamed

whenNoAncestorNamed(name: MetadataName): BindOnFluentSyntax<T>;

Constrains the binding to be used if and only if, given a name, no ancestor service was requested with the given name.

whenNoAncestorTagged

whenNoAncestorTagged(
tag: MetadataTag,
tagValue: unknown,
): BindOnFluentSyntax<T>;

Constrains the binding to be used if and only if, given a tag, no ancestor service was requested with the given tag.

whenNoParent

whenNoParent(
constraint: (metadata: BindingMetadata) => boolean,
): BindOnFluentSyntax<T>;

Constrains the binding to be used if and only if, given a constraint, no parent service matches the given constraint.

whenNoParentIs

whenNoParentIs(serviceIdentifier: ServiceIdentifier): BindOnFluentSyntax<T>;

Constrains the binding to be used if and only if, given a service identifier, no parent service was requested with the given identifier.

whenNoParentNamed

whenNoParentNamed(name: MetadataName): BindOnFluentSyntax<T>;

Constrains the binding to be used if and only if, given a name, no parent service was requested with the given name.

whenNoParentTagged

whenNoParentTagged(
tag: MetadataTag,
tagValue: unknown,
): BindOnFluentSyntax<T>;

Constrains the binding to be used if and only if, given a tag, no parent service was requested with the given tag.

whenParent

whenParent(
constraint: (metadata: BindingMetadata) => boolean,
): BindOnFluentSyntax<T>;

Constrains the binding to be used if and only if, given a constraint, the parent service matches the given constraint.

whenParentIs

whenParentIs(serviceIdentifier: ServiceIdentifier): BindOnFluentSyntax<T>;

Constrains the binding to be used if and only if, given a service identifier, the parent service was requested with the given identifier.

whenParentNamed

whenParentNamed(name: MetadataName): BindOnFluentSyntax<T>;

Constrains the binding to be used if and only if, given a name, the parent service was requested with the given name.

whenParentTagged

whenParentTagged(tag: MetadataTag, tagValue: unknown): BindOnFluentSyntax<T>;

Constrains the binding to be used if and only if, given a tag, the parent service was requested with the given tag.

whenTagged

whenTagged(tag: MetadataTag, tagValue: unknown): BindOnFluentSyntax<T>;

Constrains the binding to be used if and only if, given a tag, a tagged service is requested with the given tag.

BindWhenOnFluentSyntax

The union of BindWhenFluentSyntax and BindOnFluentSyntax.

export interface BindWhenOnFluentSyntax<T>
extends BindWhenFluentSyntax<T>,
BindOnFluentSyntax<T> {}

BindInWhenOnFluentSyntax

The union of BindInFluentSyntax and BindWhenOnFluentSyntax.

export interface BindInWhenOnFluentSyntax<T>
extends BindInFluentSyntax<T>,
BindWhenOnFluentSyntax<T> {}