Interface
多くの型システムと同様に、GraphQLはインターフェイスをサポートしています。インターフェイスは、インターフェイスを実装するために型が含まなければならないフィールドのセットを含む抽象的な型です。(ざっくりTypeScriptの
interface
と同じイメージで解釈してもらっても大丈夫です)コードファーストの場合、
@nestjs/graphql
からエクスポートされる@InterfaceType()
デコレータでアノテーションされた抽象クラスを作成することで、GraphQLインターフェイスを定義します。import { Field, ID, InterfaceType } from '@nestjs/graphql';
@InterfaceType()
export abstract class Character {
@Field((type) => ID)
id: string;
@Field()
name: string;
}
注意
TypeScriptの
interface
はGraphQLのインターフェイスを定義できません。これにより、SDLでGraphQLスキーマの以下の部分が生成されます。
interface Character {
id: ID!
name: String!
}
そこから、
Character
インターフェイスを実装するにはimplements
キーを使用します。@ObjectType({
implements: () => [Character],
})
export class Human implements Character {
id: string;
name: string;
}
メモ
@ObjectType()
デコレータは、@nestjs/graphql
パッケージからインポートします。ライブラリが生成するデフォルトの
resolveType()
関数は、resolver
メソッドから返された値に基づいて型を抽出します。つまり、クラスのインスタンスを返す必要があります(リテラルなJavaScriptオブジェクトは返せません)。カスタマイズした
resolveType()
関数を提供するには、以下のように @InterfaceType()
デコレーターに渡されるオプション・オブジェクトにresolveType
プロパティを渡します。@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 [];
}
}
これで、
Character
インターフェイスを実装するすべてのオブジェクトタイプに対して、friends
フィールドリゾルバが自動登録されるようになりました。スキーマファーストのアプローチでインターフェイスを定義するには、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
パッケージからインポートできます。Last modified 10mo ago