Working with Union Types
1. Creating Union Types
| Element | Syntax |
|---|---|
| Declaration | union Result = A | B | C |
| Members | Object types only (not interfaces, unions, scalars) |
| Common fields | None — must use ... on Type to select |
Example: Search union
union SearchResult = User | Post | Product
type Query {
search(q: String!): [SearchResult!]!
}
2. Defining Union Members
| Rule | Detail |
|---|---|
| Object only | Cannot include scalars, interfaces, unions, enums |
| Members differ | No requirement they share fields |
| Min size | At least one member required |
3. Querying Union Types
Example: Selecting from union
{
search(q: "graphql") {
__typename
... on User { id name }
... on Post { id title }
... on Product { id sku price }
}
}
| Selection | Required? |
|---|---|
| __typename | Recommended for client discrimination |
| Inline fragment | Required to access any field |
4. Using Type Conditions
| Form | Detail |
|---|---|
| Inline | ... on User { ... } |
| Named | fragment UserFields on User { ... } |
| Validation | Target must be a possible member of the union |
5. Resolving Union Types
Example: __resolveType for union
const resolvers = {
SearchResult: {
__resolveType(obj) {
if (obj.sku) return "Product";
if (obj.title) return "Post";
if (obj.email) return "User";
return null;
}
}
};
6. Creating Search Result Unions
| Member | Discriminator |
|---|---|
| User | email |
| Post | title |
| Product | sku |
| Tag | label |
7. Creating Error Unions
Example: Result-or-error union
type LoginSuccess { token: String!, user: User! }
type InvalidCredentials { message: String! }
type AccountLocked { unlockAt: DateTime! }
union LoginResult = LoginSuccess | InvalidCredentials | AccountLocked
type Mutation { login(email: String!, password: String!): LoginResult! }
8. Combining Unions with Interfaces
| Pattern | Use |
|---|---|
| Error interface + union | All errors implement UserError; union returns success or any error type |
| Node + union | Members all implement Node — clients can refetch by id |
9. Narrowing Union Types
| Tool | Detail |
|---|---|
| __typename | Switch on string in client code |
| TypeScript discriminated union | Generated types make narrowing exhaustive |
| Apollo Client | Configure possibleTypes for cache |
10. Choosing Union vs Interface
| Use Union | Use Interface |
|---|---|
| Members share NO fields | Members share fields |
| Result-or-error types | Polymorphic entities (Node, Comment owner) |
| Heterogeneous search | Common pagination/sorting |