Working with Interfaces
1. Creating Interface Types
| Element | Syntax |
|---|---|
| Declaration | interface Name { fields } |
| Required field | All implementers must provide it |
| Args | Implementer must accept same args (may add nullable extras) |
Example: Interface
interface Node { id: ID! }
interface Timestamped {
createdAt: DateTime!
updatedAt: DateTime!
}
2. Implementing Interfaces
Example: Multiple interfaces
type Post implements Node & Timestamped {
id: ID!
createdAt: DateTime!
updatedAt: DateTime!
title: String!
}
| Rule | Detail |
|---|---|
| Field set | Superset of interface fields |
| Covariance | Return type may be subtype (Node → User) |
| Multiple | Separated by & |
3. Defining Common Fields
| Common Pattern | Fields |
|---|---|
| Node | id: ID! |
| Timestamped | createdAt, updatedAt |
| Soft-deletable | deletedAt: DateTime |
| Owned | owner: User! |
4. Querying Interface Fields
Example: Interface field selection
query {
node(id: "123") {
id
__typename
... on User { email }
... on Post { title }
}
}
| Selection | Allowed |
|---|---|
| Interface fields | Direct selection |
| Concrete fields | Inline fragment ... on Type |
| __typename | Always allowed for type discrimination |
5. Resolving Abstract Types
Example: __resolveType
const resolvers = {
Node: {
__resolveType(obj) {
if (obj.email) return "User";
if (obj.title) return "Post";
return null;
}
}
};
| Approach | Detail |
|---|---|
| __resolveType | Returns concrete type name string |
| isTypeOf (per type) | Predicate function on each type |
| Discriminator field | Use a stored __type column |
6. Interface Implementing Interface
Example: Hierarchical interfaces
interface Node { id: ID! }
interface Resource implements Node {
id: ID!
url: String!
}
type Image implements Resource & Node {
id: ID!
url: String!
width: Int!
}
| Rule | Detail |
|---|---|
| Inheritance | Interface lists parent interface in implements |
| Transitive | Implementing types must list every interface in the chain |
7. Using Type Conditions
| Form | Use |
|---|---|
| Inline fragment | ... on User { email } |
| Named fragment | fragment U on User { email } |
| Validity | Type must be possible value of parent abstract type |
8. Creating Polymorphic Schemas
| Pattern | Example |
|---|---|
| Notifications | interface Notification { id, createdAt } |
| Activity Feed | Common actor, varying object |
| Search results | Union or interface across content kinds |
9. Designing Interface Hierarchies
| Guideline | Detail |
|---|---|
| Shallow | Avoid > 2 levels of interface inheritance |
| Cohesive | Group only fields semantically tied |
| Stable | Adding a field to an interface is a breaking change |
10. Choosing Interface vs Type
| Use Interface | Use Concrete Type |
|---|---|
| Multiple kinds share fields | Single, specific shape |
| Need polymorphic queries | No abstraction needed |
| Want pagination across kinds | Pagination per kind |