Interfaces
GraphQL interfaces can be defined by placing a @gqlInterface
docblock directly before an:
- Interface declaration
/**
* A description of my interface.
* @gqlInterface MyInterfaceName
*/
interface MyClass {
/** @gqlField */
someField: string;
}
Shared Field Implementation
If you wish to define field which has a single implementation that is shared by all implementors, you can use the function style of @gqlField
to define the field. This will automatically add the field to all implementors of the interface.
- TypeScript
- GraphQL
/** @gqlInterface */
interface Greetable {
/** @gqlField */
name: string;
}
/** @gqlField */
export function greeting(thing: Greetable): string {
return `Hello ${thing.name}!`;
}
/** @gqlType */
class User implements Greetable {
__typename: "User";
/** @gqlField */
name: string;
}
/** @gqlType */
class Pet implements Greetable {
__typename: "Pet";
/** @gqlField */
name: string;
}
interface Greetable {
greeting: String
name: String
}
type Pet implements Greetable {
greeting: String
name: String
}
type User implements Greetable {
greeting: String
name: String
}
Types Implementing Interfaces
To declare that a type implements an interface, see the Implementing Interfaces section of the Types docs.
Interfaces Implementing Interfaces
To declare that an interface implements another interface, you can use TypeScript's extends
keyword:
/** @gqlInterface */
interface Person {
/** @gqlField */
name: string;
}
/** @gqlInterface */
interface User extends Person {
/** @gqlField */
name: string;
/** @gqlField */
username: string;
}
Which will generate the following GraphQL schema:
interface Person {
name: String
}
interface User implements Person {
name: String
username: String
}
Overriding Interface Fields
Unlike GraphQL, when you add a field to an interface with /** @gqlField */
, the field will be automatically be added to the GraphQL definitions of all the implementors of the interface.
If you wish to override the field in a specific implementor, you can add a /** @gqlField */
with the same name to the implementor.
/** @gqlInterface */
interface Person {
/** @gqlField */
name: string;
}
/** @gqlType */
class User implements Person {
__typename = "User";
name: string;
/**
* For `User` this method will be used instead of the `name` property.
*
* @gqlField name
*/
userSpecificName(): string {
return `User: this.name`;
}
}
Merged Interfaces
TypeScript merges interfaces if you to define multiple interfaces with the same name in the same scope. For example, Node
is a built-in interface that describes DOM nodes. So, if you define a Node
interface in your code, TypeScript will merge your interface with the built-in one.
To avoid ambiguity, Grats will error if you try to define a GraphQL interface using a merged TypeScript interface. To avoid this error you can define a new interface, with a unique name, and then rename it to the name you want to use in your schema.
import { ID } from "grats";
/** @gqlType Node */
interface GqlNode {
/** @gqlField */
id: ID;
}