Unioni e Interfacce in GraphQL: Guida Completa
In GraphQL, le Unioni e le Interfacce sono strumenti avanzati che permettono di creare schemi flessibili, tipizzati e modulabili. Le Unioni consentono di definire campi che possono restituire più tipi diversi, mentre le Interfacce permettono di definire una struttura comune che può essere implementata da più tipi. Questi strumenti offrono flessibilità nella progettazione delle API e permettono di rappresentare relazioni più complesse tra i dati. In questo articolo esploreremo come utilizzare le Unioni e le Interfacce in GraphQL, con esempi pratici e best practices.
Cos’è un’Unione in GraphQL?
Un’Unione in GraphQL consente di definire un campo che può restituire uno o più tipi diversi. A differenza di un’interfaccia, i tipi che fanno parte di un’Unione non devono condividere campi comuni. Le Unioni sono utili quando un campo può restituire oggetti di tipi diversi che non hanno campi in comune.
Esempio di Definizione di Unione
union SearchResult = User | Post
In questo esempio:
SearchResult
è un’unione che può essere o unUser
o unPost
.
Utilizzo delle Unioni nelle Query
Supponiamo di voler fare una ricerca su un sito che può restituire sia utenti (User
) che post (Post
).
Definizione dello Schema
type User {
id: ID!
name: String!
email: String!
}
type Post {
id: ID!
title: String!
content: String!
}
union SearchResult = User | Post
type Query {
search(keyword: String!): [SearchResult!]!
}
In questo esempio:
- La query
search
può restituire una lista di oggetti che possono essere di tipoUser
oPost
.
Query di Esempio
query {
search(keyword: "GraphQL") {
... on User {
id
name
}
... on Post {
id
title
content
}
}
}
In questa query:
- Utilizziamo la direttiva
... on
per specificare come gestire i risultati di tipoUser
oPost
. - Se l’oggetto restituito è un
User
, richiediamoid
ename
. Se è unPost
, richiediamoid
,title
, econtent
.
Esempio di Risultato
{
"data": {
"search": [
{
"id": "1",
"name": "Alice"
},
{
"id": "101",
"title": "GraphQL Unions and Interfaces",
"content": "Learn how to use GraphQL Unions and Interfaces."
}
]
}
}
Cos’è un’Interfaccia in GraphQL?
Un’Interfaccia in GraphQL permette di definire un insieme di campi comuni che devono essere implementati da più tipi. A differenza delle Unioni, le Interfacce richiedono che i tipi che le implementano condividano un insieme di campi obbligatori.
Esempio di Definizione di un’Interfaccia
interface Node {
id: ID!
}
type User implements Node {
id: ID!
name: String!
email: String!
}
type Post implements Node {
id: ID!
title: String!
content: String!
}
In questo esempio:
- L’interfaccia
Node
definisce un campoid
che deve essere implementato sia daUser
che daPost
. - Sia
User
chePost
devono quindi avere un campoid
.
Utilizzo delle Interfacce nelle Query
L’interfaccia permette di scrivere query che possono restituire oggetti di diversi tipi, a patto che implementino la stessa interfaccia.
Definizione dello Schema con Interfaccia
interface Node {
id: ID!
}
type User implements Node {
id: ID!
name: String!
}
type Post implements Node {
id: ID!
title: String!
}
type Query {
nodes: [Node!]!
}
In questo esempio:
- La query
nodes
restituisce una lista di oggetti che implementano l’interfacciaNode
, quindi può restituire siaUser
chePost
.
Query di Esempio con Interfaccia
query {
nodes {
id
... on User {
name
}
... on Post {
title
}
}
}
In questa query:
- La direttiva
... on
viene utilizzata per richiedere campi specifici in base al tipo di oggetto (User
oPost
).
Esempio di Risultato
{
"data": {
"nodes": [
{
"id": "1",
"name": "Alice"
},
{
"id": "101",
"title": "Understanding GraphQL Interfaces"
}
]
}
}
Differenza tra Unioni e Interfacce
Sebbene le Unioni e le Interfacce sembrino simili, hanno usi diversi e caratteristiche distinte:
-
Campi Comuni:
- Interfacce: I tipi che implementano un’interfaccia devono condividere almeno un insieme di campi comuni.
- Unioni: I tipi in un’unione non devono condividere campi comuni.
-
Utilizzo:
- Interfacce: Usate quando diversi tipi devono condividere una struttura simile e il client deve conoscere i campi comuni.
- Unioni: Usate quando un campo può restituire più tipi, ma questi tipi non hanno campi in comune.
-
Estensibilità:
- Interfacce: Possono essere estese e implementate da diversi tipi, creando una gerarchia tipizzata.
- Unioni: Permettono più libertà poiché i tipi non hanno obblighi di condividere campi.
Best Practices per Unioni e Interfacce
- Usa Unioni per Tipi Completamente Diversi: Se i tipi non condividono alcun campo comune, è preferibile utilizzare un’Unione.
- Usa Interfacce per Strutture Comuni: Se più tipi condividono un insieme di campi, un’Interfaccia ti permette di tipizzare meglio i dati e semplificare le query.
- Fornisci Risolutori per le Unioni e Interfacce: Nei risolutori, devi specificare come identificare e risolvere i diversi tipi all’interno delle Unioni o delle Interfacce.
Risolutore per Unioni
const resolvers = {
SearchResult: {
__resolveType(obj) {
if (obj.name) {
return "User";
}
if (obj.title) {
return "Post";
}
return null;
},
},
};
In questo esempio, il risolutore per l’Unione SearchResult
identifica se l’oggetto è un User
o un Post
in base ai campi presenti.
Risolutore per Interfacce
const resolvers = {
Node: {
__resolveType(obj) {
if (obj.name) {
return "User";
}
if (obj.title) {
return "Post";
}
return null;
},
},
};
In modo simile, per l’interfaccia Node
, il risolutore determina il tipo di oggetto restituendo il nome del tipo.
Conclusione
Le Unioni e le Interfacce in GraphQL sono strumenti potenti che permettono di modellare dati flessibili e ben tipizzati. Usare le Unioni ti permette di gestire campi che possono restituire più tipi diversi, mentre le Interfacce ti permettono di definire strutture comuni tra diversi tipi. Scegliere tra Unioni e Interfacce dipende dalla natura dei tuoi dati e dai campi comuni o distintivi tra i tipi. Implementando correttamente Unioni e Interfacce, puoi creare API GraphQL più robuste, flessibili e scalabili.