v0.279.0 Breaking Changes

This release changes the strawberry.Maybe type definition to provide a more consistent and intuitive API for handling optional fields.

What Changed

The Maybe type definition has been changed from:

Maybe: TypeAlias = Union[Some[Union[T, None]], None]

to:

Maybe: TypeAlias = Union[Some[T], None]

Impact on Your Code

Type Annotations

If you were using Maybe[T] and expecting to handle explicit null values, you now need to explicitly declare this with Maybe[T | None] :

# Before (0.278.0 and earlier)
field: strawberry.Maybe[str]  # Could handle Some(None)
 
# After (0.279.0+)
field: strawberry.Maybe[str]  # Only handles Some("value") or None (absent)
field: strawberry.Maybe[str | None]  # Handles Some("value"), Some(None), or None

Runtime Behavior

The runtime behavior changes to provide more consistent field checking:

This means Maybe[str] can no longer receive explicit null values - they will cause a validation error.

Consistent Field Checking

This change provides a single, consistent way to check if a field was provided, regardless of whether the field allows null values:

@strawberry.input
class UpdateUserInput:
    # Can be provided with a value or not provided at all
    name: strawberry.Maybe[str]
 
    # Can be provided with a value, provided as null, or not provided at all
    phone: strawberry.Maybe[str | None]
 
 
@strawberry.mutation
def update_user(input: UpdateUserInput) -> User:
    # Same checking pattern for both fields
    if input.name is not None:  # Field was provided
        user.name = input.name.value  # Type checker knows this is str
 
    if input.phone is not None:  # Field was provided
        user.phone = input.phone.value  # Type checker knows this is str | None

The key benefit is that if field is not None now consistently means “field was provided” for all Maybe fields.

Migration

Automatic Migration

Strawberry provides a codemod to automatically update your code:

strawberry upgrade maybe-optional

The codemod will automatically convert Maybe[T] to Maybe[T | None] to maintain the previous behavior.

Manual Migration

Review your Maybe usage and decide whether you need the union type:

# If you only need "present" vs "absent" (most common case)
field: strawberry.Maybe[str]
 
# If you need "present with value", "present but null", and "absent"
field: strawberry.Maybe[str | None]

Why This Change?

After extensive discussion, we decided that changing Maybe to Some[T] | None (instead of Some[T | None] | None ) provides the best developer experience because:

  1. Consistent field checking: You can always use if field is not None: to check if a field was provided, regardless of whether the field allows null values

  2. Preserves existing behavior: You can still get the previous behavior by using Maybe[T | None] when you need to handle explicit nulls

  3. Better type safety: Maybe[str] now properly indicates that the field cannot be null, while Maybe[str | None] explicitly allows nulls

  4. Cleaner API: There’s now “one true way” to check if a field was provided, making the API more intuitive

The new approach provides both simplicity for common cases and flexibility for complex scenarios where null handling is needed.

Need Help?

Edit this page on GitHub