Skip to main content

Working with Input Types

1. Defining Input Object Types

RuleDetail
Keywordinput (not type)
Field typesOnly scalars, enums, other inputs, lists thereof
No resolversPure data shape
No interfaces/unionsNot allowed in inputs

Example: Input definition

input CreateUserInput {
  email: String!
  name: String!
  role: Role = USER
  metadata: JSON
}

2. Using Input Types in Arguments

Example: Single input arg pattern

type Mutation {
  createUser(input: CreateUserInput!): CreateUserPayload!
  updateUser(id: ID!, input: UpdateUserInput!): UpdateUserPayload!
}
PatternWhy
Single input argEasy to evolve without breaking signatures
Required inputForce client to send the object

3. Nesting Input Objects

Example: Nested address input

input AddressInput {
  street: String!
  city: String!
  country: String!
}

input CreateOrderInput {
  customerId: ID!
  shipTo: AddressInput!
  items: [OrderItemInput!]!
}

4. Setting Input Field Defaults

FormBehavior
field: T = literalUsed when field omitted
field: T! = literalRequired type, default applies if omitted
Object literalfilter: F = { active: true }

5. Validating Input Data

LayerMechanism
Type systemRequired fields, scalar type, enum values
Custom scalarsFormat-level (Email, URL)
Directives@constraint(minLength: 1)
ResolverCross-field business rules

6. Creating Reusable Inputs

PatternExample
Pagination inputinput PageInput { first: Int, after: String }
Filter inputinput StringFilter { eq, in, contains }
Sort inputinput SortInput { field, direction }

7. Input vs Output Types

AspectInputOutput (type)
Keywordinputtype
DirectionClient → ServerServer → Client
Allowed fieldsScalar/Enum/Input/ListAny (incl. interfaces, unions)
ResolversNonePer field
Args on fieldsNoYes
Warning: Never reuse an output type as an argument. Define a parallel input.

8. Naming Input Types

PatternExample
CRUDCreateXInput, UpdateXInput, DeleteXInput
FilterXFilter or XWhereInput
SortXOrderBy

9. Using OneOf Input Objects

AspectDetail
Directive@oneOf NEW
RuleExactly one field must be provided, non-null
UsePolymorphic inputs (lookup by id OR slug OR email)

Example: OneOf input

input UserBy @oneOf {
  id: ID
  email: String
  username: String
}

type Query {
  user(by: UserBy!): User
}

10. Handling Optional Input Fields

ConventionMeaning
Omitted"Don't change" (PATCH semantics)
Explicit null"Clear value" (only if field is nullable)
Empty list"Replace with no items"
Note: Detect omitted vs null in resolvers using info.fieldNodes or pre-parse args; many ORMs treat undefined as "skip".

Was this article helpful?