Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@ constructor injection.

- [TSyringe](#tsyringe)
- [Installation](#installation)
- [Babel](#babel)
- [API](#api)
- [Decorators](#decorators)
- [injectable()](#injectable)
- [singleton()](#singleton)
- [autoInjectable()](#autoinjectable)
- [inject()](#inject)
- [injectAll()](#injectall)
- [injectWithTransform()](#injectWithTransform)
- [injectAllWithTransform()](#injectAllWithTransform)
- [injectWithTransform()](#injectwithtransform)
- [injectAllWithTransform()](#injectallwithtransform)
- [scoped()](#scoped)
- [Container](#container)
- [Injection Token](#injection-token)
Expand All @@ -31,8 +32,8 @@ constructor injection.
- [Child Containers](#child-containers)
- [Clearing Instances](#clearing-instances)
- [Circular dependencies](#circular-dependencies)
- [The `delay` helper function](#the-delay-helper-function)
- [Interfaces and circular dependencies](#interfaces-and-circular-dependencies)
- [The `delay` helper function](#the-delay-helper-function)
- [Interfaces and circular dependencies](#interfaces-and-circular-dependencies)
- [Disposable instances](#disposable-instances)
- [Full examples](#full-examples)
- [Example without interfaces](#example-without-interfaces)
Expand Down Expand Up @@ -193,7 +194,7 @@ need to make the parameters optional, e.g. `database?: Database`.
### inject()

Parameter decorator factory that allows for interface and other non-class
information to be stored in the constructor's metadata.
information to be stored in the constructor's metadata. It also accepts a [provider](#providers) as a second parameter, which will be registered within the global container and can act as a fallback value in case no other registrations are done.

#### Usage

Expand Down
49 changes: 49 additions & 0 deletions src/__tests__/global-container.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,55 @@ test("allows explicit array dependencies to be resolved by inject decorator", ()
expect(bar.foo === fooArray).toBeTruthy();
});

test("allows inject to provide a default value, which will be used if not registered in other ways", () => {
@injectable()
class Foo {}

const fooArray = [new Foo()];

@injectable()
class Bar {
constructor(@inject("FooArray", {useValue: fooArray}) public foo: Foo[]) {}
}

globalContainer.register<Bar>(Bar, {useClass: Bar});

const bar = globalContainer.resolve<Bar>(Bar);
expect(bar.foo === fooArray).toBeTruthy();
});

test("allows inject to provide a default value, if injected afterwards it will be overwritten", () => {
@injectable()
class Bar {
constructor(
@inject("MyString", {useValue: "MyDefaultString"}) public foo: string
) {}
}
const str = "NewString";
globalContainer.register("MyString", {useValue: str});

globalContainer.register<Bar>(Bar, {useClass: Bar});

const bar = globalContainer.resolve<Bar>(Bar);
expect(bar.foo === str).toBeTruthy();
});

test("allows inject to have other kinds of provider", () => {
@injectable()
class Bar implements IBar {
public value = "";
}

@injectable()
class FooWithInterface {
constructor(@inject("IBar", {useClass: Bar}) public myBar: IBar) {}
}

const myFoo = globalContainer.resolve(FooWithInterface);

expect(myFoo.myBar instanceof Bar).toBeTruthy();
});

// --- @injectAll ---

test("injects all dependencies bound to a given interface", () => {
Expand Down
14 changes: 11 additions & 3 deletions src/decorators/inject.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import {defineInjectionTokenMetadata} from "../reflection-helpers";
import {instance as globalContainer} from "../dependency-container";
import {Provider} from "../providers";
import InjectionToken from "../providers/injection-token";
import {defineInjectionTokenMetadata} from "../reflection-helpers";

/**
* Parameter decorator factory that allows for interface information to be stored in the constructor's metadata
* Parameter decorator factory that allows for interface information to be stored in the constructor's metadata.
*
* If a defaultProvider is given it will be registered into the global container.
*
* @return {Function} The parameter decorator
*/
function inject(
token: InjectionToken<any>
token: InjectionToken<any>,
defaultProvider?: Provider<any>
): (target: any, propertyKey: string | symbol, parameterIndex: number) => any {
if (defaultProvider !== undefined) {
globalContainer.register(token, defaultProvider as any);
}
return defineInjectionTokenMetadata(token);
}

Expand Down