1

I'm working on a backend solution in Node.js and Express, using Typescript. I'm trying to do dependency injection similar to Angular, but lacking the @Injectable() decorator I'm doing this:

Dependency:

export class SomeDependency {
  public someMethod() {
    console.log('Some method is running');
  }
}

Parent:

import { SomeDependency } from './someDependency';

export class Whatever {

  constructor(
    private someDependency = new SomeDependency()
  ) {}

  public doSomething() {
    console.log('Look, I\'m doing something!');
    this.someDependency.someMethod();
  }
}

It works, but it may not be the best way. Any suggestions on how to improve it are appreciated.

On the other hand, what do you guys think: is it better to import dependencies like this, in the constructor, or create new instance every time, or most of the time? Like this:

import { SomeDependency } from './someDependency';

export class Whatever {

  public doSomething() {
    console.log('Look, I\'m doing something!');
    new someDependency().someMethod();
  }
}

As SomeDependency isn't a singleton, I wonder which one is less efficient: keeping an instance alive in the parent, or creating a new one every time, letting the garbage collector take care of it when the call finished.

4
  • IMO, I'd suggest only using a class when you need to bundle data together with methods that operate on that data. If you have only methods, a plain function (or object of functions) would make more sense. If you have only data, a plain object or array would make more sense. For this example here, I'd do import { someMethod } from './someMethod'; where someMethod is the function - then just call the function whenever needed. Commented Aug 23, 2020 at 21:08
  • 1
    I think a lot of the confusion and overuse of classes may come from those with OO backgrounds like Java - but JS is quite different Commented Aug 23, 2020 at 21:11
  • Thanks, but this is just a simple example of a more complex thing I'm doing. The dependency is usually a controller or Express middleware with dozens of methods. So importing just a single function won't do. Commented Aug 23, 2020 at 22:28
  • 1
    Hi, do you know tsyringe or typedi or inversifyJs for dependency injection tools? Also this post Dependency injection stackoverflow may help you :-) Commented Dec 11, 2020 at 10:43

2 Answers 2

1

your use case is absolutely correct. It is always a good practice to keep your modules as lightly coupled. So, in future you can switch between the implementation without touching the main logic but the Javascript or Typescript doesn't provide the dependency injection mechanism.

To achieve this you can use a library know as Inversify.

Inversify is powerful and lightweight inversion of control container for JavaScript & NodeJS. It implements IoC and allow us to inject dependencies, uncoupling our method from any implementation details

It give you the same functionality as we use in Angular like you can annotate the class with @Injectable() annotation and perform dependency injection.

For reference you can go to: https://www.linkedin.com/pulse/how-use-dependency-injection-nodejs-typescript-projects-ribeiro

Sign up to request clarification or add additional context in comments.

Comments

1

You may want to look into Dime. It's a very simple library I made for dependency injection similar to Angular. There are more details on the Github page and the wiki. It's still in early development, so there might be bugs.

Example:

import { ItemsService } from './items-service'; // ItemsService is an interface
import { Inject } from '@coined/dime';

class ItemsWidget {
    @Inject()
    private itemsService: ItemsService;

    render() {
        this.itemsService.getItems().subscribe(items => {
            // ...
        })
    }
}

// Setup
const appPackage = new Package("App", {
    token: "itemsService",
    provideClass: AmazonItemsService // Use any implementation
});

Dime.mountPackages(appPackage);

// Run the application
const widget = new ItemsWidget();
widget.render();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.