Skip to content

Conversation

yurahuchok
Copy link

@yurahuchok yurahuchok commented Jun 6, 2024

🏷️ Internally registered tokens / Known Classes and Known Factories

You can register class tokens internally in the classes that need to be provided, and then provide such classes by using the provideClass method's overload. To implement the "Known Class", add a static knownAs property with a string literal value. This way, it is possible to create a hierarchy of class dependencies without relying on arbitrarily specified tokens, instead opting to consolidate said tokens within the classes themselves.

import { createInjector } from 'typed-inject';

class Foo {
  static knownAs = "FooToken" as const;
}

class Bar {
  static knownAs = "BarToken" as const;

  static inject = [ Foo.knownAs ] as const;

  constructor(foo: Foo) {}
}

const injector = createInjector()
  .provideClass(Foo)
  .provideClass(Bar);

Similarly, it works with provideFactory method's overload.

import { createInjector } from 'typed-inject';

function fooFactory() {
  return "foo factory called";
}
fooFactory.knownAs = 'Foo' as const;

function barFactory() {
  return "bar factory called";
}
barFactory.inject = [ fooFactory.knownAs ] as const;
barFactory.knownAs = "Bar" as const;

const injector = createInjector()
  .provideFactory(fooFactory)
  .provideFactory(barFactory);

@nicojs
Copy link
Owner

nicojs commented Dec 13, 2024

This is very interesting. I've got a couple of remarks.

  1. Could we also implement this for provideFactory?
  2. Could we use overloading on the existing provideClass and provideFactory functions? I find the "provideInjectableXxx" naming scheme confusing, as classes provided by provideClass are also injectable.
  3. Could we rename injectableAs to knownAs? Or maybe injectionToken. Not sure about it yet.

Sorry it took me so (incredibly) long to review. I didn't see this PR for years.

@yurahuchok
Copy link
Author

This is very interesting. I've got a couple of remarks.

  1. Could we also implement this for provideFactory?
  2. Could we use overloading on the existing provideClass and provideFactory functions? I find the "provideInjectableXxx" naming scheme confusing, as classes provided by provideClass are also injectable.
  3. Could we rename injectableAs to knownAs? Or maybe injectionToken. Not sure about it yet.

Sorry it took me so (incredibly) long to review. I didn't see this PR for years.

Thank you for the reply, and no worries on the delay.

  1. Absolutely, I think the same thing can be implemented for provideFactory without issue.

  2. I agree on the topic of overloading too. I will investigate further, and implement if possible.

  3. We can definitely rename injectableAs to injectionToken. I agree it would provide additional clarity, since we already use the term "token", and this is essentially a wrapper for that.

I will update this pull request soon, and let you know.

Off-topic: Since you mentioned provideFactory, I feel compelled to voice my opinion here. To be honest I generally found the implementation of provideFactory very confusing personally, and quite limiting when dealing with async bootstrapping (based on remote config values for example). Perhaps it can be updated to solve this issue, but I didn't spend any time on that. I instead use "factory" classes and inject them with provideClass and find it sufficient for the same use-case. But that's a whole different topic.

@nicojs
Copy link
Owner

nicojs commented Jan 28, 2025

I will update this pull request soon, and let you know.

Thanks! I will keep an eye on this :)

when dealing with async bootstrapping

I've been thinking about async a lot. We can make an async variant of provideFactory, maybe called provideAsync? It must cascade all injectXxx methods since they must also be async. We might need to duplicate the code to make this work, but it is doable IMO

yurahuchok and others added 8 commits April 8, 2025 00:18
BREAKING CHANGE: Please use Node 18 or higher
- Simplify error messages
- Allow for near-infinite deep dependency trees.

Co-authored-by: Nico Jansen <[email protected]>
Add a new function to create a child injector, named `createChildInjector`. Contrary to its `provideXxx` counterparts,this will create a new disposable scope without providing additional injectable values.
@yurahuchok
Copy link
Author

Hi @nicojs !

How have you been? I finally got around to implementing the changes we talked about before. So sorry for the delay!

I have given it some thought and went with your original suggestion of calling this new property "knownAs", and subsequently calling this mechanics "Known Classes" and "Known Functions".

So as previously agreed:

  1. Feature also implemented for provideFactory.
  2. Overloading implemented for provideClass and provideFactory.
  3. The internal token renamed to knownAs.

Please review this when you can, and let me know what you think. Particularly, about the branding of this feature.

Cheers!

@yurahuchok yurahuchok changed the title feat: add mechanics to provide classes with internally registered tokens feat: add mechanics to provide classes and factories with internally registered tokens Apr 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants