This chapter follows Object types and scalars.
Arguments attach to a single field (user(id: ID!)). Input object types group arguments for mutations and complex filters. The spec forbids using output object types as inputs, so you duplicate shape where needed—a deliberate constraint that keeps evolution predictable.
Field arguments and defaults
Arguments can be scalars, enums, lists, or input objects:
type Query { events( after: DateTime limit: Int = 20 status: EventStatus = SCHEDULED ): [Event!]!}Default values apply when the client omits the argument. Changing a default is a behavioral change: old clients may see different results without a schema break.
Input object types
Input types use the input keyword. Fields may reference scalars, enums, or other input types—not output object types:
input CreateEventInput { name: String! startsAt: DateTime! venue: VenueInput}
input VenueInput { city: String! room: String}
type Mutation { createEvent(input: CreateEventInput!): Event!}The Relay mutation convention names one field input and wraps client payloads that way; many schemas follow it for consistency with codegen and libraries.
Why inputs and outputs differ
Output types can include recursive object graphs (Author.books → Book.author). Input types must be serializable trees with no cycles. You cannot pass a full Book object graph as a mutation argument unless you define a matching input shape.
That separation also lets you mark input fields optional for partial updates while keeping output fields non-null for clients reading data.
One input type per mutation
Sharing one input type across unrelated mutations couples their evolution. When CreatePostInput and UpdatePostInput diverge, shared fields like title can block you from making title optional on update only.
Prefer small, purpose-built inputs even if they look repetitive in SDL.
The @oneOf input directive
GraphQL @oneOf (when supported by your server) marks an input object where exactly one field must be provided—useful for discriminated unions in mutations:
input NotificationChannel @oneOf { email: EmailNotification sms: SmsNotification}Clients send one branch; validation fails if zero or multiple fields are set. Check your framework version; NestJS and recent spec drafts document support paths.
Where validation belongs
GraphQL validates types and requiredness before resolvers run. Business rules (unique email, stock limits) belong in resolvers or service layers and should surface as field errors or mutation payloads your schema documents.
Do not rely on GraphQL alone to enforce cross-field constraints on inputs; return structured errors your UI can display.
Next: Writing GraphQL operations.
Check your understanding
Question 1 of 6
0 of 6 checked