Reputation: 783
I am trying to setup my graphql resover to handle an array of objects but cant get the @Args decorator configured.
I created my own ArgsType
import { ArgsType, Field, Int, ObjectType } from '@nestjs/graphql';
@ArgsType() // to be used as type in the resolver
@ObjectType() // for schema generation
export class Club {
@Field(type => String)
president: string;
@Field(type => Int)
members?: number;
}
Resolver with adding a single Club works just fine!
@Query(() => Int)
async addClub(@Args() club: Club) {
// handle stuff
}
but if I want to give an array of Club like this
@Query(() => Int)
async addClubs(@Args({name: 'clubs', type: () => [Club]}) clubs: Array<Club>) {
// handle stuff
}
this thows an error when nest is starting up
UnhandledPromiseRejectionWarning: Error: Cannot determine a GraphQL input type for the "clubs". Make sure your class is decorated with an appropriate decorator.
although I am able to use an array of Strings like this
@Query(() => [String])
async addStrings(@Args({ name: 'clubs', type: () => [String], }) clubs: Array<string>) {
// handle stuff
}
I am pretty sure there should be an easy solution, but cant figure out where to go from here.
Upvotes: 20
Views: 13357
Reputation: 5804
According to the error,
Cannot determine a GraphQL input type for the "clubs". Make sure your class is decorated with an appropriate decorator
You're trying to use Club
class as a GraphQL input type while it is already an object type (According to @ObjectType
annotation you use).
Solution 1:
I would suggest you write a separate GraphQL input type like below (not tested). This is cleaner and less coupled if you need to separate the way you treat input and output of Club
.
import { InputType, Field } from '@nestjs/graphql';
@InputType()
export class ClubInput {
@Field()
president: string;
@Field()
members?: number;
}
Then in your resolver, you can use it like below.
@Query(() => Int)
async addClubs(@Args({name: 'clubs', type: () => [ClubInput]}) clubs: Array<ClubInput>) {
// handle stuff
}
Solution 2:
But if you really need to use the same class for both purposes, you could try to create both input and object types with the same Club
name. The name of the object type is by default the name of the class. So you need to provide the name explicitly to avoid conflict.
import { Field, Int, ObjectType, InputType } from '@nestjs/graphql';
@InputType("ClubInput")
@ObjectType("ClubType")
export class Club {
@Field(type => String)
president: string;
@Field(type => Int)
members?: number;
}
Now your Club
has different names for input and object types. Then in your resolver, you can use it like below.
@Query(() => Int)
async addClubs(@Args({name: 'clubs', type: () => [ClubInput]}) clubs: Array<ClubInput>) {
// handle stuff
}
Note: In this solution, you need to make sure that Club
will never contain fields that express circular references or references to interfaces and unions. If that is going to happen, you will have to move to Solution 1, else this will make your input throw an error.
The take away is that in Typescript GraphQL, InputType
and ObjectType
are two different concepts and we need to use it properly to avoid any issues.
Upvotes: 29