You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

手动调用Nest.js Injectable装饰器无法注册服务及解析依赖如何解决

问题根因

你手动调用Injectable()的逻辑本身是正确的,依赖无法解析的核心原因是TypeScript默认不会给动态生成的类注入构造函数参数的类型元数据。

常规写法下只要开启了tsconfig.json的emitDecoratorMetadata配置,TypeScript会在编译阶段自动给带装饰器的静态类附加design:paramtypes元数据,Nest的DI容器正是依靠这个元数据解析构造函数的依赖。而动态生成的类不会触发编译阶段的元数据生成逻辑,因此DI容器无法识别构造函数需要注入的依赖类型。

可行的解决步骤

  • 方案1:手动绑定构造函数参数类型元数据
    用Reflect API手动给生成的类附加参数类型元数据即可,示例代码:

    import { Injectable } from '@nestjs/common';
    import { Dep1 } from './dep1.service';
    import { Dep2 } from './dep2.service';
    
    const className = 'MyService';
    const generatedClass = {
      [className]: class { 
        constructor(dep1, dep2) {
          this.dep1 = dep1;
          this.dep2 = dep2;
        } 
      }
    }[className]
    
    // 注册为可注入服务
    Injectable()(generatedClass);
    // 手动注入构造函数参数类型元数据
    Reflect.defineMetadata('design:paramtypes', [Dep1, Dep2], generatedClass);
    
  • 方案2:手动调用@Inject()标记参数
    如果你需要使用自定义注入Token而非类类型做依赖标记,可以直接调用Inject装饰器给对应位置的参数做标记:

    import { Injectable, Inject } from '@nestjs/common';
    import { DEP1_TOKEN } from './constants';
    
    const className = 'MyService';
    const generatedClass = {
      [className]: class { 
        constructor(dep1) {
          this.dep1 = dep1;
        } 
      }
    }[className]
    
    Injectable()(generatedClass);
    // 给第0位构造参数标记注入Token
    Inject(DEP1_TOKEN)(generatedClass, undefined, 0);
    
  • 额外注意:动态生成的类无法被模块的自动扫描逻辑识别,需要你显式加到对应模块的providers数组中:

    @Module({
      providers: [generatedClass],
      exports: [generatedClass]
    })
    export class AppModule {}
    

内容的提问来源于stack exchange,提问作者plusheen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 21:06:03