手动调用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
相关产品推荐
相关产品推荐

