Closed rainerschuster closed 3 years ago
Hi @rainerschuster I'll have a look. Thank you for your report
Hi @rainerschuster it makes sense to me to update the actual behavior to cover your expectations. What do you think @PodaruDragos , @dcavanagh?
hi @notaphplover isn't the behavior correct ? https://github.com/inversify/InversifyJS/issues/411#issuecomment-264651698
Hi @PodaruDragos , I am not sure, I've been reading the docs:
In the example we can see how the first time we resolve
Ninja
, its propertyshuriken
is undefined because no bindings have been declared forShuriken
and the property is annotated with the@optional()
decorator.After declaring a binding for
Shuriken
:container.bind<Shuriken>("Shuriken").to(Shuriken);
All the resolved instances of
Ninja
will contain an instance ofShuriken
.
So I think if the binding is declared, the @optional()
decorator should make no difference in the behaviour, but if we remove the @optional()
decorator, the behaviour changes.
If we look the current implementation of whenTargetIsDefault
:
public whenTargetIsDefault(): interfaces.BindingOnSyntax<T> {
this._binding.constraint = (request: interfaces.Request) => {
const targetIsDefault = (request.target !== null) &&
(!request.target.isNamed()) &&
(!request.target.isTagged());
return targetIsDefault;
};
return new BindingOnSyntax<T>(this._binding);
}
It seems to be all right but, looking at Target.isTagged()
implementation:
public isTagged(): boolean {
return this.metadata.some((m) =>
(m.key !== METADATA_KEY.INJECT_TAG) &&
(m.key !== METADATA_KEY.MULTI_INJECT_TAG) &&
(m.key !== METADATA_KEY.NAME_TAG) &&
(m.key !== METADATA_KEY.UNMANAGED_TAG) &&
(m.key !== METADATA_KEY.NAMED_TAG));
}
It's kind of weird, if the target has the optional()
decorator, is it supposed to be tagged? I think this is a bug and the right implementation would be:
public isTagged(): boolean {
return this.metadata.some((m) =>
(m.key !== METADATA_KEY.INJECT_TAG) &&
(m.key !== METADATA_KEY.MULTI_INJECT_TAG) &&
(m.key !== METADATA_KEY.NAME_TAG) &&
(m.key !== METADATA_KEY.UNMANAGED_TAG) &&
(m.key !== METADATA_KEY.NAMED_TAG) &&
(m.key !== METADATA_KEY.OPTIONAL_TAG));
}
which would solve the issue, the optional()
decorator would be transparent when there's a binding for the service and would give isTagged
method more sense
Hi @rainerschuster the issue is fixed in the master branch now! :)
Thanks for fixing!
You are very welcome :smiley: we expect to release a new version soon, I'm closing the issue. Feel free to ping me if anything is wrong and I'll reopen it immediately.
If a property is declared as @optional and the types are bound with whenTargetIsDefault the property is undefined.
Expected Behavior
The following example should inject Katana for the optional katana field.
Current Behavior
katana is undefined. If the decorator optional is removed it works as expected.
Possible Solution
use container.get(TYPES.Weapon);
Steps to Reproduce (for bugs)
Your Environment