Could Inversify help TypeScript perform type check on an ServiceIdentifier I use with @inject decorator?
See original GitHub issueExpected Behavior
I’d like typescript to warn me if I used @inject decorator with service ID (a symbol) pointing to something that doesn’t match property’s type.
Current Behavior
I can have a property set up with a type but I can use whatever ID I want and I will not figure it out until I’ll try to use that property in a runtime.
Possible Solution
Maybe it would be possible for Inversify to somehow support stuff like e.g. io-ts (https://github.com/gcanti/io-ts) type objects as service ids?
Context
// ...
@injectable()
class MyClass implementes IMyClass {
constructor(
// I should put ITokenStorage.ID here
// but I can put totally wrong ID here and nothing will stop me.
// I won't figure it out until I try to use that tokenStorage in a runtime.
@inject(ISomeDataRepository.ID) private tokenStorage: ITokenStorage,
) {}
}
I keep my IDs under namespaces that share the same names as the interfaces so it helps me easily notice the mistake with my eyes but it’s still possible and easy to make such mistakes.
The same goes for binding. Yes, you provide generic typings that will catch an attempt to use wrong class with an interface specified as T (which is great) but I can still type in the wrong ID and inversify won’t notice.
It all works great (at least for binding) if I use a class as ID. I understand that interfaces disappear in runtime but using abstract classes as abstract types for services doesn’t exactly feel right (although it’s interesting how TypeScript can treat an abstract class as an implementable interface that stays in a runtime 😄 )
Issue Analytics
- State:
- Created 5 years ago
- Reactions:4
- Comments:6
Top Related StackOverflow Question
Thanks for the suggestion, I will try this out.
Another way to write it, fyi:
What I found out:
You can leave away the
@inject, but only if you leave it away for all the arguments. As I need to mix string service identifiers and class service identifiers, the@injectneeds to stay (for now).The type error message, when something goes wrong is a little confusing.
Consider this toy example:
Now when we incorrectly bind
KatanatoThrowableWeaponwithwe get a nice error message:
When we try to use
toServicethoughthe error message is not helpful at all:
When using
bind(ThrowableWeapon).toService(Weapon), inversify does not type checkKatanaagainstThrowableWeapon, but instead checksWeaponagainstThrowableWeapon.So if we had a
Katanathat implemented bothWeaponandThrowableWeapon, we would have to use a more complex syntax to achieve proper type checking. Directly binding both to different instances ofKatanawould work of course. Otherwise the following does the trick:It is not very beautiful though.
Luckily this case is rare.