Is there a way to use static method with dependency injection in NestJS?

Viewed 3882

An example is better than a long explanation:

// Backery.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Backery } from './Backery.entity';

@Injectable()
export class BackeryService {
  constructor(
    @InjectRepository(Backery)
    private readonly backeryRepository: Repository<Backery>,
  ) {}

  static myStaticMethodToGetPrice() {
    return 1;
  }

  otherMethod() {
    this.backeryRepository.find();
    /* ... */
  }
}
// Backery.resolver.ts
import { Bakery } from './Bakery.entity';
import { BakeryService } from './Bakery.service';

@Resolver(() => Bakery)
export class BakeryResolver {
  constructor() {}

  @ResolveField('price', () => Number)
  async getPrice(): Promise<number> {
    return BakeryService.myStaticMethodToGetPrice(); // No dependency injection here :(
  }
}

How can I replace BakeryService.myStaticMethodToGetPrice() to use dependency injection, so I can test things easily for example?

2 Answers

Static methods cannot use dependency injection. This is because the idea of dependency injection (at least to Nest) is to inject instances of the dependencies so that they can be leveraged later.

The code you have is valid, in that it will return the value 1 like the static method says to, but the static method cannot use any of the instance values that are injected. You'll find this kind of logic follows in most other DI frameworks.

There is a very easy way to create static functions that use services from your NestJs DI.

One good example is the use for Domain Events and avoiding polluting your entities' constructors with technical services.

In your main.ts

let app: INestApplication;

async function bootstrap() {
  app = await NestFactory.create(AppModule);

  install();
  ...
  ...
}

bootstrap();

export const getInstance = () => {
  return app;
};

From any static context within your app:

import { getInstance } from '@/main';

static async emmitEvent() {
    let eventEmitter = await getInstance().resolve(EventEmitter2);
    eventEmitter.emit(JSON.stringify(nodeCreateEvent));
}
Related