1

I want to pass "Interfaces" to a function. Not a specific interface, but any interfaces.

As described here, for Class, I can handle it as a type.

export type ClassType<T> = { new(...args: any[]): T };

function doSomethingWithAnyClass<T>(anyClass: ClassType<T>) {...}

My question is: Can I do the same thing for an Interface?

All Classes have constructor and they can be called a { new(...args: any[]): T } type. Then what about Interface? How do I represent an "Interface" type?

Edit

I'm writing a small DI library. When I register a dependency, I pass a pair of "class"(as token) and a "function that creates an instance of that class"(as factory). The pairs of token and factory are saved in a map structure. When resolving a dependency, I pass the token to a resolver function.

For example, let's say I have a class FileLogger and someone needs an instance of it. I want to register the dependency and resolve it from wherever it is needed. So I register a factory () => new FileLogger with a token FileLogger, and then resolve by resolve<FileLogger>(FileLogger)(It takes a generic type parameter which is redundant here but I left it to reveal that it does).

The problem is, an interface cannot be used as a token, because it is not a value. I looked for how other DI library solved this problem and found that tsyringe just uses string as token when dealing with interface.

For now, I ended up changing interfaces into abstract classes. However, I'm not happy with it and about to look for another approach.

Potados
  • 177
  • 1
  • 9
  • Please consider making this code into a [mcve] which shows examples of what you'd like to accept and reject being passed into `doSomethingWithAnyInterface()`. When you say "any class" you apparently mean "any class *constructor*" according to your code. I'm not sure what you mean by "any interface". The empty object type `{}` should be a supertype of any possible interface, but that's so wide that it only rejects `null` and `undefined`. If you're looking for something more specific than that, I'd really like to see use cases. – jcalz Apr 22 '21 at 02:39
  • @jcalz I'm sorry that I missed it. I'v edited the question. Thanks. – Potados Apr 22 '21 at 21:18
  • @Potados "ended up changing interfaces into abstract classes. However, I'm not happy with it " Can you please elaborate a bit on this? Whats wrong with abstract classes? – Stupid Man Apr 23 '21 at 01:10
  • 1
    @StupidMan As it refactored to a "class", I have to **extend**, not **implement**, it in every child class, thus forced to call `super()` in constructor. Every method in the abstract class must bring *abstract* prefix. Above all, abstract class is not suitable for my use case. I'd like to replace implementations for test, by extracting method declarations to an interface. Although abstract class can mimic an interface, it is not designed for that. What I need is interface. – Potados Apr 23 '21 at 01:44

1 Answers1

1

Absolutely not.

Don't confuse types (interfaces, types, enums, etc) with values (boolean, string, object, array, function, etc).

Values can be arguments and each value has a type but an argument cannot be a type.

Alex Mckay
  • 3,463
  • 16
  • 27