Skip to main content

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;
}
Playground

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.

/** @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;
}
Playground

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;
}
Playground

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`;
}
}
Playground

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;
}
Playground