Hacker News new | ask | show | jobs
by WHATDOESIT 1373 days ago
An ES module is encapsulated enough. You can dependency inject with them as you wish. It's like having a class, no need for a class inside a class.

The biggest argument is that my functional-ish code is always 3x shorter with the same features, though.

2 comments

This. Creating classes to wrap dependencies is a pattern only needed because of language limitations. With JS/TS, you can mock at the import statement level, so no need to twist your code to abstract away importing.

Also, even if you didn't want to mock that way, you can get dependency injection with functions just by taking a parameter for a dependency. If dependency injection is the only reason you have to use a class, you probably shouldn't use a class.

Request-scoped DI (as seen in ASP.NET MVC) is great on the backend for servicing requests. You can ask for e.g. a class representing the current user information to be injected anywhere, or to keep track of request-associated state like opentelemetry spans, or a transaction, etc. The alternative is to pass the user information class or transaction to all other services, which can be annoying

Its rarely seen in the ecosystem as a solution, unfortunately (everyone is passing all arguments all the time), but its one of the rare places where this is still useful. I've had bad experience with the alternative (continuation local storage) and its not nearly as elegant.

The IoC is a nice paradigm that I tried using with a couple different libraries in JS, but they all felt like they had missing features and sometimes were annoying to run tests with (depending on the how they implemented the IoC container within their frameworks). The work Microsoft puts into their web frameworks to make them so cohesive with the rest of their ecosystem libraries is sometimes underrated
Yeah, the designs of DI libraries in TS land often leave me wondering what the author was thinking.
How do you dependency inject a ES module?
You'll export a function from your esModule if you want to inject

export const myFn = (...deps) =>

You don't need anything else, for encapsulation you have the EsModule, that what OP meant.

ah, thanks, I thought it was something different.
You have dynamic imports too if you need IoC.