Tipi Input in GraphQL: Guida Completa
In GraphQL, i tipi input vengono utilizzati per passare dati strutturati come argomenti nelle mutazioni e, in alcuni casi, anche nelle query. Mentre i tipi standard descrivono la forma dei dati restituiti dal server, i tipi input sono utilizzati per definire la forma dei dati inviati dal client al server. In questo articolo esploreremo cosa sono i tipi input, come definirli e come utilizzarli efficacemente per migliorare la flessibilità delle API GraphQL.
Cosa sono i Tipi Input in GraphQL?
Un tipo input in GraphQL è un tipo personalizzato che consente di strutturare e validare i dati in ingresso nelle mutazioni o query. Questi tipi possono contenere campi scalari come String
, Int
, Boolean
, ma anche campi più complessi. I tipi input non possono contenere risolutori o relazioni tra tipi, poiché il loro scopo è semplicemente quello di descrivere la forma dei dati che il client può inviare al server.
Esempio di Tipo Input
input CreateUserInput {
name: String!
email: String!
age: Int
}
In questo esempio, CreateUserInput
è un tipo input che accetta un name
, un email
obbligatori e un age
opzionale.
Differenze tra Tipi Standard e Tipi Input
- Tipi standard (es.
User
,Post
) descrivono i dati che il server restituisce nelle query o mutazioni. - Tipi input (es.
CreateUserInput
) descrivono i dati che il client invia al server durante una mutazione o query.
I tipi standard possono contenere relazioni con altri tipi e possono essere restituiti nelle query, mentre i tipi input sono progettati esclusivamente per l’invio dei dati dal client.
Definizione di un Tipo Input
I tipi input sono definiti utilizzando la parola chiave input
, seguita dal nome del tipo e dalla lista dei campi che lo compongono. I campi possono essere scalari (String
, Int
, Float
, Boolean
, ID
), liste o altri tipi input.
Esempio di Definizione di un Tipo Input
input UpdateUserInput {
id: ID!
name: String
email: String
age: Int
}
In questo esempio, il tipo UpdateUserInput
definisce i dati necessari per aggiornare un utente. Poiché si tratta di un aggiornamento, i campi name
, email
e age
sono facoltativi, ma l’id
dell’utente è obbligatorio.
Utilizzo dei Tipi Input nelle Mutazioni
I tipi input sono comunemente utilizzati nelle mutazioni per passare dati complessi in modo strutturato.
Esempio di Mutazione con Tipo Input
type Mutation {
createUser(input: CreateUserInput!): User!
}
In questo esempio:
- La mutazione
createUser
accetta un argomento chiamatoinput
di tipoCreateUserInput
. - La mutazione restituisce un oggetto di tipo
User
dopo aver creato il nuovo utente.
Esempio di Query della Mutazione
Per inviare la mutazione createUser
utilizzando un tipo input:
mutation {
createUser(input: { name: "Alice", email: "alice@example.com", age: 25 }) {
id
name
email
}
}
In questo esempio:
- Il client invia un oggetto
input
con i campiname
,email
, eage
alla mutazionecreateUser
. - La mutazione restituisce l’utente appena creato con i campi
id
,name
, eemail
.
Definizione e Utilizzo di Tipi Input Annidati
I tipi input possono contenere altri tipi input per rappresentare dati complessi o strutture annidate. Questo è utile quando hai bisogno di passare oggetti strutturati come indirizzi, profili o configurazioni dettagliate.
Esempio di Tipo Input Annidato
input AddressInput {
street: String!
city: String!
zipCode: String!
}
input CreateUserInput {
name: String!
email: String!
address: AddressInput
}
In questo esempio, il tipo CreateUserInput
include un campo address
di tipo AddressInput
. Questo permette al client di inviare dati strutturati per l’indirizzo dell’utente.
Utilizzo di Tipi Input Annidati
Quando utilizzi tipi input annidati, il client può inviare strutture complesse in modo organizzato:
mutation {
createUser(
input: {
name: "Bob"
email: "bob@example.com"
address: { street: "123 Main St", city: "Milan", zipCode: "20100" }
}
) {
id
name
email
address {
street
city
zipCode
}
}
}
In questo esempio, il client invia sia i dati dell’utente che i dettagli dell’indirizzo come parte dell’oggetto input
.
Validazione dei Tipi Input
GraphQL, per sua natura, applica una validazione automatica sui tipi input. Se i dati inviati non rispettano lo schema definito (es. un campo mancante o un tipo errato), GraphQL restituirà un errore senza eseguire la mutazione.
Esempio di Validazione Automatica
Se invii una mutazione senza fornire un campo obbligatorio, come email
, GraphQL restituirà un errore simile al seguente:
{
"errors": [
{
"message": "Field 'email' of required type 'String!' was not provided.",
"locations": [{ "line": 3, "column": 5 }],
"extensions": {
"code": "GRAPHQL_VALIDATION_FAILED"
}
}
]
}
Questa validazione automatica garantisce che i dati inviati siano conformi allo schema definito, riducendo la necessità di ulteriori controlli lato server.
Best Practices per l’Utilizzo dei Tipi Input
- Riutilizza i Tipi Input per Mutazioni Correlate: Se più mutazioni richiedono strutture di input simili (es.
createUser
eupdateUser
), riutilizza i tipi input dove possibile. - Segui una Nomenclatura Consistente: Utilizza una convenzione di denominazione chiara, come
CreateUserInput
,UpdateUserInput
, oDeleteUserInput
, per rendere il codice più leggibile. - Mantieni i Tipi Input Modulari: Se un tipo input diventa troppo complesso, suddividilo in parti più piccole utilizzando tipi input annidati.
- Non Usare Tipi Complessi nei Tipi Input: Evita di utilizzare tipi complessi come
User
oPost
all’interno di un tipo input, poiché questo può creare confusione nella definizione dei dati in ingresso. - Validazione Personalizzata: Sebbene GraphQL fornisca una validazione di base, per vincoli più specifici (es. validazione di formati email o intervalli numerici), considera l’implementazione di una validazione lato server nei risolutori.
Conclusione
I tipi input in GraphQL sono strumenti potenti che permettono di strutturare i dati in ingresso nelle mutazioni e, talvolta, nelle query. Forniscono una chiara definizione della forma dei dati che il client deve inviare e semplificano la gestione delle operazioni complesse. Utilizzando tipi input ben definiti e seguendo le best practices, puoi creare API robuste, modulari e manutenibili.