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

如何将Model传递给共享抽象Resolver(控制器)

问题

我有多个Resolver,所有Resolver都继承自一个抽象Resolver。现在需要将Model传递给这个抽象Resolver,并且要在@Query和@ResolveField装饰器中使用它。之前尝试通过构造函数传递Model,但提示Model可能未定义。

相关代码示例:

抽象Resolver:

@Resolver(() => EntityModel)
export abstract class EntityResolver<M, CMD, UMD> {
  protected constructor(protected service: EntityService<M>) {}

  @RolesGuards([ROLES.USER])
  @ResolveField(() => /* MODEL */)
  @Query(() => /* MODEL */)
  async findAll(): Promise<{ response: M[]; statusCode: number }> {
    return {
      statusCode: HttpStatus.OK,
      response: await this.service.findAll(),
    }
  }
}

具体UsersResolver:

@Resolver(() => Users)
export default class UsersResolver extends EntityResolver<Users, CreateUsersDto, UpdateUsersDto> {
  constructor(protected service: UsersService) {
    super(service)
  }

  @RolesGuards([ROLES.ADMIN])
  @Get('/email/:email')
  async findByEmail(
    @Param('email') email: string,
  ): Promise<{ response: Users; statusCode: number }> {
    return {
      statusCode: HttpStatus.OK,
      response: await this.service.findByEmail(email),
    }
  }
}

UsersModule:

@Module({
  controllers: [UsersController],
  providers: [UsersService, UsersResolver],
  imports: [SequelizeModule.forFeature([Users]), RolesModule, LoggerModule],
  exports: [SequelizeModule, UsersService],
})
export class UsersModule {}

EntityModel基类:

@ObjectType()
export class EntityModel<M, MCA = {}> extends Model<M, MCA> {
  user_id: string;
}

Users实体类:

interface UserCreationAttrs {
  id: string
  email: string
  password: string
}


@ObjectType()
@Table({ tableName: 'Users' })
export class Users extends EntityModel<Users, UserCreationAttrs> {
  @Column({
    type: DataType.STRING,
    unique: true,
    primaryKey: true,
  })
  id: string

  @Column({ type: DataType.STRING, unique: true, allowNull: false })
  email: string

  @Column({ type: DataType.STRING, allowNull: false })
  password: string

  @BelongsToMany(() => Roles, () => UsersRoles)
  roles: Roles[]

  @HasMany(() => Funds)
  funds: Funds[]

  @HasMany(() => Expense)
  expense: Expense[]

  @HasMany(() => ExpenseCategories)
  expenseCategories: ExpenseCategories[]

  @HasMany(() => Income)
  income: Income[]

  @HasMany(() => IncomeCategories)
  incomeCategories: IncomeCategories[]
}
解决方案

核心思路

NestJS的装饰器(如@Query、@ResolveField)在类定义阶段执行,无法访问实例化阶段才赋值的构造函数属性。因此需要通过静态属性传递Model类,让装饰器在类定义时就能获取到具体的Model类型。

步骤1:改造抽象Resolver

新增受保护的静态属性model,用于存储子类传递的具体Model类;同时修改装饰器,直接引用该静态属性指定返回类型:

import { Resolver, Query, ResolveField } from '@nestjs/graphql';
import { HttpStatus } from '@nestjs/common';
import { RolesGuards } from './your-roles-guard-path';
import { ROLES } from './your-roles-path';
import { EntityService } from './your-entity-service-path';
import { EntityModel } from './your-entity-model-path';

export abstract class EntityResolver<M, CMD, UMD> {
  // 静态属性,子类需赋值具体Model类
  protected static model: typeof EntityModel;

  protected constructor(protected service: EntityService<M>) {}

  @RolesGuards([ROLES.USER])
  // 指定返回Model数组类型
  @Query(() => [this.model])
  async findAll(): Promise<{ response: M[]; statusCode: number }> {
    return {
      statusCode: HttpStatus.OK,
      response: await this.service.findAll(),
    };
  }

  // 若需定义ResolveField,同样用this.model指定类型
  @ResolveField(() => this.model)
  async exampleField(): Promise<M> {
    // 自定义逻辑
  }
}

步骤2:子类赋值静态Model属性

在具体Resolver子类中,给静态属性model赋值当前对应的Model类(如Users),其余逻辑保持不变:

import { Resolver } from '@nestjs/graphql';
import { Get, Param } from '@nestjs/common';
import { HttpStatus } from '@nestjs/common';
import { RolesGuards } from './your-roles-guard-path';
import { ROLES } from './your-roles-path';
import { EntityResolver } from './entity.resolver';
import { Users } from './users.entity';
import { UsersService } from './users.service';
import { CreateUsersDto, UpdateUsersDto } from './your-dto-path';

@Resolver(() => Users)
export default class UsersResolver extends EntityResolver<Users, CreateUsersDto, UpdateUsersDto> {
  // 赋值静态属性,绑定当前Model类
  protected static model = Users;

  constructor(protected service: UsersService) {
    super(service);
  }

  @RolesGuards([ROLES.ADMIN])
  @Get('/email/:email')
  async findByEmail(
    @Param('email') email: string,
  ): Promise<{ response: Users; statusCode: number }> {
    return {
      statusCode: HttpStatus.OK,
      response: await this.service.findByEmail(email),
    };
  }
}

说明

  • 静态属性在类定义时就已初始化,装饰器可以直接访问到,完美适配NestJS装饰器的执行时机。
  • 这种方式不需要额外依赖,代码简洁且能复用抽象Resolver的通用逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 02:39:54