Skip to content

Internally generate symbols/identifiers; optional-identifiers-happy-path? #534

@atrauzzi

Description

@atrauzzi

I'm interested in knowing if there could be a way where symbol/identifier management isn't mandatory when using inversify for certain types of injections.
I feel like I mostly understand why they exist and what purpose they serve (some injections don't correspond to a distinct type).

Some point-form thoughts

  • Isn't this something reflect-metadata should be helping with?
  • inversify must already maintain its own internal table of symbols for types, it's just that right now, the requirement is that it be populated from outside the container
  • I suspect this will only work with things where the types are distinct and metadata is available - which means classes. But without implying that this is specific to my use case, that's the only time that this kind of arrangement would be nice to have (see next point).
  • My trusty reference for dynamically-typed-with-oo-sprinkled-in, Laravel, actually might have some worthwhile inspiration.

The idea is that you have a scenario where the IoC becomes minimum-touch. It's a convention where the container only receives queries for instances by their static type and - barring any overrides - uses reflection to do the rest. Instead of it being mandatory to painstakingly describe the connections between types, you simply have to ensure your constructor parameters are clearly defined. With Laravel, you don't even have to inform the container of a type prior to looking it up! Actually, as far as I can tell, internally I think the Laravel DI system only uses strings to track types.

In the case of inversify and TypeScript/ECMAScript, the equivalent here would be to internally generate symbols/identifiers whenever the container sees a new type. Then, subsequent "naked" lookups of the type would result in that same - already established - symbol being internally rediscovered and used.

What this might eliminate

(please correct me if I'm wrong here!)

  • The need to put @injectable on classes
  • The need to explicitly declare constructor parameter bindings
  • The need to bind static types when their constructors only require unambiguous reflectable types

I'd effectively be able to say context.get(MyStaticType) and get back an instance, having done no other preparation in advance.

What this would not eliminate

  • The concept of symbols/identifiers
  • Requirement to use symbols/identifiers when declaring and injecting constants, factories and other ambiguous types

Why?

Mainly to reduce boilerplate, code maintenance, and the margin of cognitive overhead that comes with them. As I've been putting together my first non-contrived protoculture solution, I've discovered that because I'm using inversify, implementers are forced into managing their own symbols. Even though they may not be adding any ambiguous types to the container.
My first instinct was to try and hide this by managing the symbols/identifiers myself in some of my framework classes. But then my mind started pushing that responsibility down...down...down.
Which eventually got me to thinking about whether there could be a way to avoid these requirements entirely provided a specific set of rules were observed. And of course, with Laravel serving as an example, I'm sure there could be a way to have inversify offer the same. This is a total guess - but I don't think it would be too disruptive either?

This idea would go nicely with what's already been done here: #505 - in fact, when selectively designed for it, a request for a type could effectively cause its entire dependency graph to self-wire.
And of course nothing I'm suggesting here implies that the existing mechanisms to bind types should be eliminated. So caveats in the dependency graph can still be accommodated and self wiring would just continue beyond and around it.

More than happy to go into an extended discussion about this if needed. But I feel like it should be possible and would take this already great (I'm not going anywhere!) container and push it to yet-even-higher-heights.

🖋️

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions