GraphQL Input Types
Input types let you group multiple arguments together into a single named object. Instead of passing five separate arguments to a mutation, you define an input type with those five fields and pass one structured object. This keeps mutations clean and makes complex argument lists manageable.
The Problem Input Types Solve
Without input types, a mutation to create a user might have a long, messy argument list that is hard to read and validate.
Without input type — messy argument list:
──────────────────────────────────────────
type Mutation {
createUser(
firstName: String!
lastName: String!
email: String!
password: String!
phone: String
role: UserRole!
): User!
}
With input type — clean and grouped:
─────────────────────────────────────
input CreateUserInput {
firstName: String!
lastName: String!
email: String!
password: String!
phone: String
role: UserRole!
}
type Mutation {
createUser(input: CreateUserInput!): User!
}
Defining an Input Type
Input types use the keyword input instead of type. They look similar to object types but serve a different purpose — input types flow from client to server, while object types flow from server to client.
input BookingInput {
hotelId: ID!
checkIn: String!
checkOut: String!
guests: Int!
roomType: RoomType!
}
type Mutation {
bookRoom(booking: BookingInput!): Reservation!
}
Using an Input Type in a Mutation
Query (mutation):
──────────────────
mutation CreateBooking {
bookRoom(booking: {
hotelId: "h42",
checkIn: "2025-06-01",
checkOut: "2025-06-05",
guests: 2,
roomType: DELUXE
}) {
id
confirmationCode
totalPrice
}
}
Input Types Can Be Nested
Input types can contain other input types, allowing you to build structured, hierarchical input objects that match complex data models.
input AddressInput {
street: String!
city: String!
country: String!
}
input RegisterInput {
name: String!
email: String!
password: String!
address: AddressInput! ← nested input type
}
type Mutation {
register(data: RegisterInput!): User!
}
Mutation:
──────────
mutation {
register(data: {
name: "Priya",
email: "priya@example.com",
password: "securepass",
address: {
street: "12 Oak Street",
city: "Mumbai",
country: "India"
}
}) {
id
name
}
}
Input Types vs Object Types — Key Difference
input Type type (Object Type) ────────────── ────────────────── Used as argument Used as return value Client → Server Server → Client Cannot have resolvers Can have resolvers Cannot have arguments Fields can have arguments on its fields on their fields
Default Values in Input Types
Fields in an input type can have default values. If the client does not provide the field, the server uses the default.
input PaginationInput {
page: Int = 1
perPage: Int = 20
}
type Query {
products(pagination: PaginationInput): [Product]
}
Query without pagination — defaults apply:
───────────────────────────────────────────
{ products { name } } → page 1, 20 per page
Query with pagination — overrides defaults:
────────────────────────────────────────────
{ products(pagination: { page: 3, perPage: 5 }) { name } }
