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.
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> {}