diff --git a/src/resolution/instantiation.ts b/src/resolution/instantiation.ts index 8e4537176..66b7976b4 100644 --- a/src/resolution/instantiation.ts +++ b/src/resolution/instantiation.ts @@ -68,7 +68,9 @@ function createInstanceWithInjections( args.propertyRequests.forEach((r: interfaces.Request, index: number) => { const property = r.target.identifier; const injection = args.propertyInjections[index]; - (instance as Record)[property] = injection; + if (!r.target.isOptional() || injection !== undefined) { + (instance as Record)[property] = injection; + } }); return instance } diff --git a/test/annotation/optional.test.ts b/test/annotation/optional.test.ts index 1230e813b..d2e610b65 100644 --- a/test/annotation/optional.test.ts +++ b/test/annotation/optional.test.ts @@ -107,4 +107,49 @@ describe('@optional', () => { }); + it("Should allow to set a default value for class property dependencies flagged as optional", () => { + @injectable() + class Katana { + public name: string; + public constructor() { + this.name = 'Katana'; + } + } + + @injectable() + class Shuriken { + public name: string; + public constructor() { + this.name = 'Shuriken'; + } + } + + @injectable() + class Ninja { + public name: string = "Ninja"; + @inject("Katana") public katana?: Katana; + @inject("Shuriken") @optional() public shuriken: Shuriken = { + name: "DefaultShuriken", + }; + } + + const container = new Container(); + + container.bind('Katana').to(Katana); + container.bind('Ninja').to(Ninja); + + let ninja = container.get('Ninja'); + expect(ninja.name).to.eql('Ninja'); + expect(ninja.katana?.name).to.eql('Katana'); + expect(ninja.shuriken.name).to.eql('DefaultShuriken'); + + container.bind('Shuriken').to(Shuriken); + + ninja = container.get('Ninja'); + expect(ninja.name).to.eql('Ninja'); + expect(ninja.katana?.name).to.eql('Katana'); + expect(ninja.shuriken.name).to.eql('Shuriken'); + } + ); + }); \ No newline at end of file diff --git a/wiki/optional_dependencies.md b/wiki/optional_dependencies.md index 10af62a26..ab202eb5a 100644 --- a/wiki/optional_dependencies.md +++ b/wiki/optional_dependencies.md @@ -84,3 +84,13 @@ class Ninja { } } ``` + +Or using properties injection: +```ts +@injectable() +class Ninja { + public name = "Ninja"; + @inject("Katana") public katana: Katana; + @inject("Shuriken") @optional() public shuriken: Shuriken = { name: "DefaultShuriken" } // Default value! +} +``` \ No newline at end of file