NestJS中如何在ObjectType字段注解中使用泛型声明?自定义GraphQL分页结果报错求助
The error you're seeing happens because TypeGraphQL can't infer the runtime type of the generic T in your PaginateResult class. GraphQL requires explicit type definitions for all fields, and since TypeScript generics are erased at compile time, the docs field doesn't have a concrete type attached to it in the schema.
Here are two approaches to solve this:
Approach 1: Create a Concrete Paginated Result Class (Simple)
For each type you want to paginate (like User), create a dedicated ObjectType class that explicitly defines the docs field type.
Step 1: Define User-Specific Pagination Result
import { ObjectType, Field } from '@nestjs/graphql'; import { User } from './user.entity'; // Adjust import path as needed @ObjectType() export class UserPaginateResult { // Explicitly set the type to an array of User @Field(() => [User]) docs: User[]; @Field() totalDocs: string; @Field() totalPages: string; }
Step 2: Update the Resolver to Use the Concrete Type
@Query((type) => UserPaginateResult, { nullable: true }) async getUsers(@Args({ type: () => GetAllUserArgs }) args: GetAllUserArgs) { const queryResolver: QueryResolver = new QueryResolver(args); return this.userService.getAll(queryResolver.query); }
This works because we've replaced the generic PaginateResult<User> with a concrete class that tells TypeGraphQL exactly what type docs should be.
Approach 2: Reusable Factory Function (Scalable)
If you need to paginate multiple types, creating a new class for each gets repetitive. Instead, use a factory function to dynamically generate paginated result types for any object type.
Step 1: Create a Paginate Result Factory
import { ObjectType, Field, Type } from '@nestjs/graphql'; // Define a base interface for pagination results export interface PaginateResult<T> { docs: T[]; totalDocs: string; totalPages: string; } // Factory function to generate paginated result types export function PaginateResultFactory<T>(itemType: Type<T>) { // Generate a unique name for the GraphQL type (e.g., "UserPaginateResult") @ObjectType(`${itemType.name}PaginateResult`) class PaginateResultClass implements PaginateResult<T> { @Field(() => [itemType]) docs: T[]; @Field() totalDocs: string; @Field() totalPages: string; } return PaginateResultClass; }
Step 2: Use the Factory in Your Resolver
@Query((type) => PaginateResultFactory(User), { nullable: true }) async getUsers(@Args({ type: () => GetAllUserArgs }) args: GetAllUserArgs) { const queryResolver: QueryResolver = new QueryResolver(args); return this.userService.getAll(queryResolver.query); }
Now you can reuse this factory for any type:
// For a Product type, for example @Query((type) => PaginateResultFactory(Product), { nullable: true }) async getProducts(...) { /* ... */ }
Bonus: Optional Type Improvement
Note that totalDocs and totalPages are typically numeric values. If these are supposed to be numbers instead of strings, you should update their types to number and use the Int scalar for GraphQL:
import { Int } from '@nestjs/graphql'; // In your paginate result class/factory: @Field(() => Int) totalDocs: number; @Field(() => Int) totalPages: number;
This will make your schema more accurate and avoid unnecessary string-to-number conversions.
内容的提问来源于stack exchange,提问作者masood keshvari

