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".