[英]Use the same class as Input and Object type in GraphQL in NestJS
I am trying to setup my graphql resover to handle an array of objects but cant get the @Args decorator configured.我正在尝试设置我的 graphql resover 来处理一组对象,但无法配置 @Args 装饰器。
I created my own ArgsType我创建了自己的 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这在 Nest 启动时出现错误
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.我很确定应该有一个简单的解决方案,但无法弄清楚从哪里开始。
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).您正在尝试将Club
类用作 GraphQL 输入类型,而它已经是对象类型(根据您使用的@ObjectType
注释)。
Solution 1:解决方案1:
I would suggest you write a separate GraphQL input type like below (not tested).我建议您编写一个单独的 GraphQL 输入类型,如下所示(未测试)。 This is cleaner and less coupled if you need to separate the way you treat input and output of Club
.如果您需要将处理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:解决方案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.但是如果你真的需要为这两个目的使用同一个类,你可以尝试使用相同的Club
名称创建输入和对象类型。 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.现在,您的Club
对输入和对象类型有不同的名称。 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.注意:在此解决方案中,您需要确保Club
永远不会包含表达循环引用或对接口和联合的引用的字段。 If that is going to happen, you will have to move to Solution 1, else this will make your input throw an error.如果发生这种情况,您将不得不转向解决方案 1,否则这将使您的输入引发错误。
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.需要注意的是,在 Typescript GraphQL 中, InputType
和ObjectType
是两个不同的概念,我们需要正确使用它以避免任何问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.