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

Which will generate the following GraphQL schema:

interface Person {
name: String
}

interface User implements Person {
name: String
username: String
}

note

Each implementor of an interface must define all the fields required by the interface with /** @gqlField */. This means that if you have an interface that implements another interface, you must define all the fields required by both interfaces.

Merged Interfaces​

TypeScript merges interfaces if you 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 a file without any imports or exports (whose declarations are global), 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";

/** @gqlInterface Node */
interface GqlNode {
/** @gqlField */
id: ID;
}
Playground
caution

Grats can only detect merges between declarations in the files it reads. It does not read TypeScript's built-in declarations, like the DOM's Node, so it can't report when your interface merges with one of them.