接口 Interfaces

导读

与许多类型系统一样,GraphQL 支持接口。接口 是一种抽象类型,它包含一组特定字段,类型必须包含这些字段才能实现接口 阅读更多信息,请点击此处

代码优先

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

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

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

  @Field()
  name: string
}
警告

TypeScript 接口不能用于定义 GraphQL 接口。

这将导致在 SDL 中生成以下 GraphQL 模式部分:

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

现在,要实现 Character 接口,请使用 implements 键:

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

@ObjectType() 装饰器从 @nestjs/graphql 包中导出。

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

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

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

  @Field()
  title: string
}

接口解析器

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

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

@Resolver(type => Character) // 提醒:Character 是一个接口
export class CharacterInterfaceResolver {
  @ResolveField(() => [Character])
  friends(
    @Parent() character, // 实现 Character 的解析对象
    @Info() { parentType }, // 实现 Character 的对象的类型
    @Args('search', { type: () => String }) searchTerm: string,
  ) {
    // 获取角色的朋友
    return []
  }
}

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

Schema 优先

要以 schema 优先方法定义接口,只需使用 SDL 创建 GraphQL 接口即可。

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

然后,您可以使用 typings 生成功能(如 快速入门 章节中所示)生成相应的 TypeScript 定义:

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

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

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

所有装饰器都从 @nestjs/graphql 包中导出。