在NestJS中使用与GraphQL中的Input和Object类型相同的类

时间:2020-10-30 11:31:07

标签: typescript graphql nestjs

我正在尝试设置我的graphql resover来处理对象数组,但无法配置@Args装饰器。

我创建了自己的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;
}

添加单个Club的解析器效果很好!

 @Query(() => Int)
 async addClub(@Args() club: Club) {
  // handle stuff
  }

但是如果我想提供这样的俱乐部

 @Query(() => Int)
   async addClubs(@Args({name: 'clubs', type: () => [Club]}) clubs: Array<Club>) {
   // handle stuff
  }

这会在嵌套启动时引发错误

 UnhandledPromiseRejectionWarning: Error: Cannot determine a GraphQL input type for the "clubs". Make sure your class is decorated with an appropriate decorator.

尽管我可以使用这样的字符串数组

 @Query(() => [String])
 async addStrings(@Args({ name: 'clubs', type: () => [String], }) clubs: Array<string>) {
  // handle stuff
  }

我很确定应该有一个简单的解决方案,但无法弄清楚从这里去哪里。

1 个答案:

答案 0 :(得分:6)

根据错误,

Make sure your class is decorated with an appropriate decorator

您正在尝试将Club类用作GraphQL输入类型,而该类已经是对象类型(根据您使用的@ObjectType注释)。


解决方案1:

我建议您编写一个单独的GraphQL输入类型,如下所示(未经测试)。如果您需要区分对待Club的输入和输出的方式,则这种方法更清洁,耦合性也更低。

import { InputType, Field } from '@nestjs/graphql';

@InputType()
export class ClubInput {
 @Field()
 president: string;

 @Field()
 members?: number;
}

然后在您的解析器中,可以按以下方式使用它。

@Query(() => Int)
async addClubs(@Args({name: 'clubs', type: () => [ClubInput]}) clubs: Array<ClubInput>) {
 // handle stuff
}

解决方案2:

但是,如果您确实需要同时使用相同的类来实现这两个目的,则可以尝试使用相同的Club名称创建输入和对象类型。默认情况下,对象类型的名称是类的名称。因此,您需要明确提供名称以避免冲突。

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;
}

现在,您的Club的输入和对象类型名称不同。然后,在您的解析器中,可以按以下方式使用它。

@Query(() => Int)
async addClubs(@Args({name: 'clubs', type: () => [ClubInput]}) clubs: Array<ClubInput>) {
 // handle stuff
}

注意:在此解决方案中,您需要确保Club绝不包含表示循环引用或对接口和联合的引用的字段。如果发生这种情况,则必须转到解决方案1,否则这将使您的输入抛出错误。


要解决的是,在Typescript GraphQL中,InputTypeObjectType是两个不同的概念,我们需要适当地使用它以避免出现任何问题。