Understanding Nullability Semantics

1. Understanding Null Propagation

Example: Null bubbles up

# Schema
type Query {
  user: User
}
type User {
  id: ID!
  name: String!  # non-null
}

# If name resolves to null:
# → User becomes null (User.user is nullable)
# → errors[] contains the path
PathResult
All non-null up to rootEntire data becomes null
Nullable ancestor existsThat ancestor becomes null
Sibling fieldsPreserved (partial data)

2. Making Fields Non-nullable

When to use !When to avoid
Truly always present (id, createdAt)Depends on permissions
Computed from required stateCould fail (network, integration)
List fields (prefer empty array)External data sources

3. Making Arguments Non-nullable

FormEffect
arg: T!Must be supplied, cannot be null
arg: T! = defaultRequired type, default if omitted
arg: TOptional, defaults to null

4. Handling Null Values

StrategyUse
Null guard in resolverif (!parent.x) return null;
Optional chainingparent?.address?.city
Default valueCoalesce in resolver

5. Using Null as Default

FieldReasoning
Optional update fieldsnull = unchanged
Optional filtersnull = no filter applied
Computed fieldsnull = not yet computed

6. Validating Null Inputs

Example: Distinguish omitted vs explicit null

updateUser(_, { id, input }) {
  const update = {};
  if ("name" in input) update.name = input.name;       // null = clear
  if ("email" in input) update.email = input.email;
  return db.user.update({ where: { id }, data: update });
}

7. Returning Null vs Empty

ReturnSemantics
null on object"Not found" or "no value"
[] on list"No items"
"" on stringAvoid — ambiguous; prefer null

8. Null in Lists

TypeNull Behavior
[T!]!Any null item or null list → entire list bubbles error
[T]!List required but item nulls allowed
[T!]Item must be non-null OR entire list becomes null
[T]Anything goes

9. Designing Null-safe Schemas

GuidelineDetail
Default nullableAdd ! only when guaranteed
Critical IDs non-nullid: ID! always
External data nullableThird-party calls may fail
Lists: [T!]!Empty array is enough — no need for null

10. Using Maybe Types

CodegenTypeScript Output
String!string
StringMaybe<string> = string | null | undefined
[String!]!string[]
[String]Maybe<Array<Maybe<string>>>