在 NestJs 中,如何根据其接口注入服务?

Gab*_*ile 3 javascript node.js typescript ecmascript-6 nestjs

我有下一个模块:payment.module.ts

@Module({
  controllers: [PaymentController],
})
export class PaymentModule {}
Run Code Online (Sandbox Code Playgroud)

在下一个服务中,我想访问基于接口的服务

支付服务.ts

export class PaymentService {
   constructor(private readonly notificationService: NotificationInterface,
}
Run Code Online (Sandbox Code Playgroud)

通知.interface.ts

export interface NotificationInterface {
  // some method definitions
}
Run Code Online (Sandbox Code Playgroud)

通知.service.ts

@Injectable()
export class NotificationService implements NotificationInterface {
  // some implemented methods
}
Run Code Online (Sandbox Code Playgroud)

问题是我如何注入NotificationService基于NotificationInterface

Mat*_*s S 16

正如 Gabriel 所提到的,您不能使用接口,因为它们在运行时不存在,但您可以使用抽象类。它们在运行时可用,因此可以用作依赖项注入令牌。

在 Typescript 中,类声明也会创建 types,因此您也可以实现它们,而不必扩展它们。

按照您的示例,您可以执行以下操作:

通知.interface.ts

export abstract class NotificationInterface {
  abstract send(): Promise<void>;
  // ... other method definitions
}
Run Code Online (Sandbox Code Playgroud)

通知.service.ts

export abstract class NotificationInterface {
  abstract send(): Promise<void>;
  // ... other method definitions
}
Run Code Online (Sandbox Code Playgroud)

然后在您的模块中,像这样提供它:

export class NotificationService implements NotificationInterface {
  async send() {...}
} 
Run Code Online (Sandbox Code Playgroud)

最后,通过 payment.service.ts 中的接口使用注入的服务

import NotificationInterface from "..."
import NotificationService from "..."

@Module({
  providers: [
    {
      provide: NotificationInterface,
      useClass: NotificationService
    }
  ]
})
export class PaymentModule {}
Run Code Online (Sandbox Code Playgroud)

现在,您不需要提供任何与您的类实现(并且仅是 DI 构造)有些“无关”的自定义标记(作为字符串或符号),但您可以使用 OOP 模型中的结构。


Gab*_*ile 7

这是我找到的解决方案......使用接口作为值类型是不可能的,因为它们只存在于开发过程中。转译接口后不再存在导致空对象值。尽管使用字符串键作为提供值和注入装饰器,但您的问题有一个解决方案:

支付模块.ts

@Module({
  providers: [
    {
      provide: 'NotificationInterface',
      useClass: NotificationService
    }
  ]
})
export class PaymentModule {}
Run Code Online (Sandbox Code Playgroud)

支付服务.ts

export class PaymentService {
   constructor(@Inject('NotificationInterface') private readonly notificationService: NotificationInterface,
}
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案,这是我使用的方法和推荐的解决这个问题的 NestJS (2认同)