如何将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
相关产品推荐
相关产品推荐

