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

如何在NestJS中向类注入接口实现类列表?

问题描述

我定义了如下IParser接口:

export interface IParser {
  parse(text: string): string
}

以及两个实现该接口的类:

@Injectable()
export class FirstParser implements IParser {
   public parse(text: string): string {
     return text + 'first';
   }
}

@Injectable()
export class SecondParser implements IParser {
   public parse(text: string): string {
     return text + 'second';
   }
}

现在我希望在ParserService中注入该接口的实现类列表:

@Injectable()
export class ParserService {
    constructor(private readonly parsers: IParser[]) {}

    public parse(text: string): string {
        let parsedText = text;
        parsedText = this.parsers.reduce((acc: string, result) => {
            return result.parse(acc);
        }, parsedText);
        return parsedText;
    }
}

但在配置ParserServiceModule时,不知道如何配置providers来注入包含FirstParser、SecondParser的数组:

@Module({
    providers: [
        ParserService,
        {
          provide: Array<IParser>,
          useClass: ???,
        },
    ],
})
export class ParserServiceModule {}

请问在NestJS中是否可以实现该需求?具体该如何配置?


解决方案

完全可以实现,核心是利用NestJS的自定义注入令牌和**多提供者(multi: true)**特性——因为TypeScript接口在编译为JavaScript后会被擦除,无法直接作为注入标识使用。

具体配置步骤:

  1. 创建注入令牌
    定义一个专门的令牌来标识IParser实现集合:

    import { InjectionToken } from '@nestjs/common';
    import { IParser } from './parser.interface';
    
    export const PARSERS = new InjectionToken<IParser[]>('PARSERS');
    
  2. 修改ParserService的注入逻辑
    在构造函数中通过@Inject()指定自定义令牌:

    import { Inject, Injectable } from '@nestjs/common';
    import { IParser } from './parser.interface';
    import { PARSERS } from './parser.token';
    
    @Injectable()
    export class ParserService {
        constructor(@Inject(PARSERS) private readonly parsers: IParser[]) {}
    
        public parse(text: string): string {
            return this.parsers.reduce((acc, parser) => parser.parse(acc), text);
        }
    }
    
  3. 配置模块的providers
    将每个IParser实现绑定到PARSERS令牌,并设置multi: true,NestJS会自动收集所有绑定实例组成数组:

    import { Module } from '@nestjs/common';
    import { ParserService } from './parser.service';
    import { FirstParser } from './first.parser';
    import { SecondParser } from './second.parser';
    import { PARSERS } from './parser.token';
    
    @Module({
        providers: [
            ParserService,
            FirstParser,
            SecondParser,
            {
                provide: PARSERS,
                useExisting: FirstParser,
                multi: true,
            },
            {
                provide: PARSERS,
                useExisting: SecondParser,
                multi: true,
            },
        ],
    })
    export class ParserServiceModule {}
    

简化写法

如果不需要单独导出FirstParser或SecondParser,可以直接在提供者中声明:

@Module({
    providers: [
        ParserService,
        {
            provide: PARSERS,
            useClass: FirstParser,
            multi: true,
        },
        {
            provide: PARSERS,
            useClass: SecondParser,
            multi: true,
        },
    ],
})
export class ParserServiceModule {}

关键说明

  • multi: true:告知NestJS当前令牌对应多个实例,会将所有绑定的实例收集为数组注入。
  • 自定义令牌:解决TypeScript接口无法作为注入标识的问题——接口仅存在于编译阶段,运行时会被擦除,而InjectionToken是运行时可识别的对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 14:45:46