How to pass multiple generic services into library

Help Request

Say I'm building a library, and that library has an assortment of different filter controls, like a text input, dropdown, checkbox, etc...

I then want to be able to provide a service to those filter controls, generically, preferably where I could have multiple services, each one shares a generic interface, but with a type.

FilterService<T>

UserService implements FilterService<User>

CarService implements FilterService<Car>

HouseService implements FilterService<House>

So then you have a chain of components in the library, but maybe pass T up through them.

FilterListComponent<T>

template contains multiple of these:

TextInputComponent<T>

Then, TextInputComponent<User> gets the type User, but it calls for FilterService<User>, it should get the UserService that implements the interface FilterService<User>. And later on, if you do TextInputComponent<Car> it would get the FilterService<Car>.

Can anyone point me in the right direction to accomplish something like this? It feels like it should be possible.

Posted Mar 22, 2022, 6:59 PM UTC

26
GLawSomnia•

https://youtu.be/rcDsRyVhcxY

Maybe something like the composition example here?

2
techmaster242OP•

Thanks! That looks really interesting... I might have to look into this further. Sometimes you just have to hear something described in the right way for it to make sense. I need to find a good resource to learn angular design patterns. I have yet to find anything good that goes beyond Maximillian's udemy course.

1
Merry-Lane•

When you say “implements FilterService<User>” it doesn’t mean that the user service implements it but rather requires to have the signatures of what it implements.

I think you need to use the dependency injection to put the FilterService into the constructor of your XXX service and make your service use your user/car/house/…

1
techmaster242OP•

Yeah I want to be able to have something like this:

FilterComponent<T> {
constructor(
filterService: FilterService<T>

) {}

}

The component should be able to use its <T> parameter to pick from an assortment of very similar services that all have the same interface. The interface is very simple, and really only needs 2 functions. UpdateFilter and ClearFilter. So I could have a CarService, HouseService, DogService, CatService... and they all implement FilterService<T>, but the type changes according to the service. You pass T into the FilterComponent, and it would automatically be able to see oh I'm FilterComponent<Dog> so dependency injection should inject the FilterService<Dog> which is DogService. And then all the component has to worry about is updating and clearing the filter, but not how it's actually done.

1
Merry-Lane•

I don’t know what you are trying to do but I think you are going overboard.

If in your service you do a constructor like

Contructor<T>( type: T extends { x: string, y: number,…})

(with in the extends the minimal props u need for ur service to work)

Then you should be good to go?

1
CoderXocomil•

I just did something very similar to this. Your TextInputComponent<User> should really be a TextInputComponent<UserService>. This gives you what you are asking for. If you need to get User from UserService, you can use a conditional type. For example, this playground example shows a possibility.

1