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

Fuz*_*per 9 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;
}
Run Code Online (Sandbox Code Playgroud)

添加单个俱乐部的解析器工作正常!

 @Query(() => Int)
 async addClub(@Args() club: Club) {
  // handle stuff
  }
Run Code Online (Sandbox Code Playgroud)

但如果我想像这样提供一系列俱乐部

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

这在 Nest 启动时出现错误

 UnhandledPromiseRejectionWarning: Error: Cannot determine a GraphQL input type for the "clubs". Make sure your class is decorated with an appropriate decorator.
Run Code Online (Sandbox Code Playgroud)

虽然我可以使用这样的字符串数组

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

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

Era*_*han 12

根据错误,

Cannot determine a GraphQL input type for the "clubs". Make sure your class is decorated with an appropriate decorator
Run Code Online (Sandbox Code Playgroud)

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


解决方案1:

我建议您编写一个单独的 GraphQL 输入类型,如下所示(未测试)。如果您需要分开处理Club.

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

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

 @Field()
 members?: number;
}
Run Code Online (Sandbox Code Playgroud)

然后在您的解析器中,您可以像下面那样使用它。

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

解决方案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;
}
Run Code Online (Sandbox Code Playgroud)

现在您Club有不同的输入和对象类型名称。然后在您的解析器中,您可以像下面那样使用它。

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

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


需要注意的是,在 Typescript GraphQL 中,InputTypeObjectType是两个不同的概念,我们需要正确使用它以避免任何问题。

  • https://docs.nestjs.com/graphql/mapped-types 这为您提供了一个很好的抽象来实现您的愿望 (2认同)