NestJs: Injecting classes without @Injectable()

Viewed 1538

I have certain classes/libraries that I want uncoupled from NestJs. These classes are declared as regular classes without the @Injectable decorator and may have further dependencies.

What is the best way to inject these into my Nest app? Is there a way I can decorate them as injectable after import? I've tried things like:

import { MyClass } from '@my-library/my-class';
import { MyClassDep } from '@my-library/my-class';

function makeInjectable<T>(target: Type<T>): Type<T> {
  Injectable()(target);
  return target;
}

@Module({
  controllers: [],
  providers: [
    makeInjectable(myClass),
    makeInjectable(myClassDep),
  ],
})
export class UsersModule {}

to no success. My solution so far is to use useFactory to provide these manually but it's not ideal:

import { MyClass } from '@my-library/my-class';
import { MyClassDep } from '@my-library/my-class';

@Module({
  controllers: [],
  providers: [
    { provide: MyClass, useFactory: (myClassDep: MyClassDep) => new MyClass(myDep), inject: [MyClassDep] },
    { provide: MyClassDep, useFactory: () => new MyClassDep(), inject: [] },
  ],
})
export class UsersModule {}

What is the best way to go about this?

1 Answers

Try using factory providers:

import { MyClass } from '@my-library/my-class';
import { MyClassDep } from '@my-library/my-class';

function makeInjectable<T>(target: Type<T>): Type<T> {
  return {
    provide: target.constructor.name,
    useFactory: () => new target(),
  };
}

@Module({
  controllers: [],
  providers: [
    makeInjectable(myClass),
    makeInjectable(myClassDep),
  ],
})
export class UsersModule {}
Related