# Interface Type Definition

An Interface is an abstract type that includes a certain set of fields that a
type must include to implement the interface.

## Writing Interface Types

In **graphql-php** interface type is an instance of `GraphQL\Type\Definition\InterfaceType`
(or one of its subclasses) which accepts configuration array in a constructor:

```php
use GraphQL\Type\Definition\InterfaceType;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;

$character = new InterfaceType([
    'name' => 'Character',
    'description' => 'A character in the Star Wars Trilogy',
    'fields' => [
        'id' => [
            'type' => Type::nonNull(Type::string()),
            'description' => 'The id of the character.',
        ],
        'name' => [
            'type' => Type::string(),
            'description' => 'The name of the character.'
        ]
    ],
    'resolveType' => function ($value): ObjectType {
        switch ($value->type ?? null) {
            case 'human': return MyTypes::human();
            case 'droid': return MyTypes::droid();
            default: throw new Exception("Unknown Character type: {$value->type ?? null}");
        }
    }
]);
```

This example uses **inline** style for Interface definition, but you can also use  
[inheritance or schema definition language](index.md#definition-styles).

## Configuration options

The constructor of InterfaceType accepts an array. Below is a full list of allowed options:

| Option      | Type       | Notes                                                                                                                                                                                                                                  |
| ----------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| name        | `string`   | **Required.** Unique name of this interface type within Schema                                                                                                                                                                         |
| fields      | `array`    | **Required.** List of fields required to be defined by interface implementors. Same as [Fields for Object Type](object-types.md#field-configuration-options)                                                                           |
| description | `string`   | Plain-text description of this type for clients (e.g. used by [GraphiQL](https://github.com/graphql/graphiql) for auto-generated documentation)                                                                                        |
| resolveType | `callback` | **function ($value, $context, [ResolveInfo](../class-reference.md#graphqltypedefinitionresolveinfo) $info)**<br> Receives **$value** from resolver of the parent field and returns concrete interface implementor for this **$value**. |

## Implementing interface

To implement the Interface simply add it to **interfaces** array of Object Type definition:

```php
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\ObjectType;

$humanType = new ObjectType([
    'name' => 'Human',
    'fields' => [
        'id' => [
            'type' => Type::nonNull(Type::string()),
            'description' => 'The id of the character.',
        ],
        'name' => [
            'type' => Type::string(),
            'description' => 'The name of the character.'
        ]
    ],
    'interfaces' => [
        $character
    ]
]);
```

Note that Object Type must include all fields of interface with exact same types
(including **nonNull** specification) and arguments.

The only exception is when object's field type is more specific than the type of this field defined in interface
(see [Covariant return types for interface fields](#covariant-return-types-for-interface-fields) below)

## Covariant return types for interface fields

Object types implementing interface may change the field type to more specific.
Example:

```graphql
interface A {
  field1: A
}

type B implements A {
  field1: B
}
```

## Sharing Interface fields

Since every Object Type implementing an Interface must have the same set of fields - it often makes
sense to reuse field definitions of Interface in Object Types:

```php
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\ObjectType;

$humanType = new ObjectType([
    'name' => 'Human',
    'interfaces' => [
        $character
    ],
    'fields' => [
        $character->getField('id'),
        $character->getField('name'),
        [
            'name' => 'height',
            'type' => Type::float(),
        ],
    ]
]);
```

In this case, field definitions are created only once (as a part of the Interface Type) and then reused by all interface implementors.
It can save several microseconds and kilobytes and ensures that field definitions of Interface and implementors are always in sync.
Yet it creates a problem with the resolution of such fields.

There are two ways how shared fields could be resolved:

1. If the field resolution algorithm is the same for all Interface implementors,
   you can add the **resolve** option to the field definition in the Interface itself.

2. If field resolution varies for different implementations, you can specify the **resolveField** option
   in [the Object Type config](object-types.md#configuration-options) and handle field resolutions there.
   (Note: The **resolve** option in field definitions has precedence over the **resolveField** option in object type definitions.)

## Interface role in data fetching

The only responsibility of interface in Data Fetching process is to return concrete Object Type
for given **$value** in **resolveType**. Then resolution of fields is delegated to resolvers of this
concrete Object Type.

If a **resolveType** option is omitted, graphql-php will loop through all interface implementors and
use their **isTypeOf** callback to pick the first suitable one. This is obviously less efficient
than single **resolveType** call. So it is recommended to define **resolveType** whenever possible.

## Prevent invisible types

When object types that implement an interface are not directly referenced by a field, they cannot
be discovered during schema introspection. For example:

```graphql
type Query {
    animal: Animal
}

interface Animal {...}

type Cat implements Animal {...}
type Dog implements Animal {...}
```

In this example, `Cat` and `Dog` would be considered _invisible_ types. Querying the `animal` field
would fail, since no possible implementing types for `Animal` can be found.

There are two possible solutions:

1. Add fields that reference the invisible types directly, e.g.:

   ```graphql
   type Query {
     dog: Dog
     cat: Cat
   }
   ```

2. Pass the invisible types during schema construction, e.g.:

```php
new GraphQLSchema([
    'query' => ...,
    'types' => [$cat, $dog]
]);
```
