| title | 0.279.0 Breaking Changes |
|---|---|
| slug | breaking-changes/0.279.0 |
This release changes the strawberry.Maybe type definition to provide a more
consistent and intuitive API for handling optional fields.
The Maybe type definition has been changed from:
Maybe: TypeAlias = Union[Some[Union[T, None]], None]to:
Maybe: TypeAlias = Union[Some[T], None]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 NoneThe runtime behavior changes to provide more consistent field checking:
Maybe[str]now represents "field present with non-null value" or "field absent"Maybe[str | None]represents "field present with value", "field present but null", or "field absent"
This means Maybe[str] can no longer receive explicit null values - they will
cause a validation error.
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 | NoneThe key benefit is that if field is not None now consistently means "field was
provided" for all Maybe fields.
Strawberry provides a codemod to automatically update your code:
strawberry upgrade maybe-optionalThe codemod will automatically convert Maybe[T] to Maybe[T | None] to
maintain the previous behavior.
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]After extensive discussion, we decided that changing Maybe to Some[T] | None
(instead of Some[T | None] | None) provides the best developer experience
because:
-
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 -
Preserves existing behavior: You can still get the previous behavior by using
Maybe[T | None]when you need to handle explicit nulls -
Better type safety:
Maybe[str]now properly indicates that the field cannot be null, whileMaybe[str | None]explicitly allows nulls -
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.
- See the Maybe documentation for comprehensive usage examples
- Check the migration guide for detailed migration instructions
- If you encounter issues, please report them on GitHub