NestJS 9 GraphQL 中文文档(六) - 接口

302 阅读2分钟

像许多类型系统一样,GraphQL也支持接口。接口是一种抽象类型,它包括一组特定的字段,类型必须包含这些字段才能实现接口(在此阅读更多)。

代码优先

当使用代码优先方式时,你可以通过创建一个抽象类来定义一个GraphQL接口,该抽象类使用从@nestjs/graphql 中导出的 @InterfaceType() 装饰器注释。

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

@InterfaceType()
export abstract class Character {
  @Field((type) => ID)
  id: string;

  @Field()
  name: string;
}

警告⚠️
TypeScript 接口不能被用来定义 GraphQL接口。

最终在SDL中生成GraphQL schema的以下部分:

interface Character {
  id: ID!
  name: String!
}

注意,要实现该Character接口,需使用implements关键词:

@ObjectType({
  implements: () => [Character],
})
export class Human implements Character {
  id: string;
  name: string;
}

提示
@ObjectType() 装饰器是从@nestjs/graphql包里导出的。

库生成的默认resolveType() 函数根据解析器方法返回的值提取类型。这意味着你必须返回类实例(你不能返回JavaScript对象字面量)。

要提供一个自定义的resolveType() 函数,将resolveType属性传递给@InterfaceType() 装饰器中的可选对象,如下所示:

@InterfaceType({
  resolveType(book) {
    if (book.colors) {
      return ColoringBook;
    }
    return TextBook;
  },
})
export abstract class Book {
  @Field((type) => ID)
  id: string;

  @Field()
  title: string;
}

接口解析器

到目前为止,你使用接口的方式只是与你的对象共享字段定义。如果你还想共享实际的字段解析器实现,你可以创建一个专用的接口解析器,如下所示:

import { Resolver, ResolveField, Parent, Info } from '@nestjs/graphql';

@Resolver(type => Character) // Reminder: Character is an interface
export class CharacterInterfaceResolver {
  @ResolveField(() => [Character])
  friends(
    @Parent() character, // Resolved object that implements Character
    @Info() { parentType }, // Type of the object that implements Character
    @Args('search', { type: () => String }) searchTerm: string,
  ) {
    // Get character's friends
    return [];
  }
}

现在friends字段解析器就会被实现Character 接口的所有对象类型自动注册。

模式优先

在模式优先方式中定义接口,只需使用SDL简单地创建一个GraphQL接口。

interface Character {
  id: ID!
  name: String!
}

然后,你可以使用类型生成功能(如快速入门一章中所示)来生成对应的TypeScript定义:

export interface Character {
  id: string;
  name: string;
}

接口在解析器映射中需要一个额外 __resolveType 字段来确定接口应该解析为哪个类型。让我们创建一个CharactersResolver 类并定义 __resolveType 方法:

@Resolver('Character')
export class CharactersResolver {
  @ResolveField()
  __resolveType(value) {
    if ('age' in value) {
      return Person;
    }
    return null;
  }
}

提示
所有的装饰器都是从@nestjs/graphql包里导出的。