-
-
Notifications
You must be signed in to change notification settings - Fork 555
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Type-safe "optional-nullable" fields #3779
Comments
To clarify, is the following the use case you're interested in? mutation Update {
updatePerson( ## this operation sets phone to null
input: {
id: ...,
name: ...,
phone: null
}
) {
...
}
} vs mutation Update {
updatePerson( ## this operation does not modify phone number
input: {
id: ...,
name: ...
}
) {
...
}
} |
yep |
I think this is a solid proposal. Both For an opt-in approach, I would prefer your solution: strawberry.register_option_type((MyOptionType, NOTHING)) If this Type is meant to be included directly in Strawberry, I would avoid forking the repository. Instead, I’d suggest copying the relevant MIT-licensed code while ensuring proper attribution, such as adding credits in the form of code comments or including a reference to the original license. |
@patrick91 👀 ? |
Code sample in pyright playground from __future__ import annotations
import dataclasses
from typing import Self, reveal_type
@dataclasses.dataclass
class Some[T]:
value: T
def some(self) -> Self:
return self
@dataclasses.dataclass
class Nothing[T]:
def some(self) -> None:
return None
type Maybe[T] = Some[T | None] | Nothing[T]
def some_func() -> Maybe[str]:
return Some("a")
a = some_func()
reveal_type(a)
if phone := a.some():
reveal_type(phone)
reveal_type(phone.value)
else:
reveal_type(phone) |
I have met the exact same problem, but I don't understand why you cannot solve it.
The case where you do not want None but either a string or nothing cannot be handled cleanly due to the GraphQL specification (an optional value is a nullable value**), but if your API is used only internally, you can do the same thing:
(Arguably you could write custom code to ensure that sending a None would return an appropriate error instead of randomly breaking inside your code) I find the proposition slightly contrived, as it turns scalar values into objects. |
phone: str | None | UnsetType can actually solve this, I haven't thought about this really... Though:
phone: str | None = strawberry.UNSET You could say that we can change the signature to the real type but that would type-checkers would lint
We could also think re-introducing the Unset usage which could look like this type Maybe[T] = UnsetType | None | T
def is_unset[T](val: T | UnsetType) -> TypeGuard[UnsetType]:
return isinstance(val, UnsetType)
@strawberry.input
class UpdatePersonInput:
phone: Maybe[str]
def update_person(input_: UpdatePersonInput) -> ...:
if not strawberry.is_unset(input_.phone)
update_phone(input_.phone) I actually have no oppositions to this. |
Preface
it is a common practice in strawberry that when your data layer have
an optional field i.e
and you want to update it you would use
UNSET
in the mutation inputin order to check whether this field provided by the client or not like so:
Note that this is not an optimization rather a business requirement.
if the user wants to nullify the phone it won't be possible other wise
OTOH you might nullify the phone unintentionally.
This approach can cause lots of bugs since you need to remember that you have
used
UNSET
and to handle this correspondingly.Since strawberry claims to
it is only natural for us to provide a typesafe way to mitigate this.
Proposal
The
Option
type.which will require only this minimal implementationand this is how you'd use it
Currently if you want to know if a field was provided
Backward compat
UNSET
can remain as is for existing codebases.Option
would be handled separately.which
Option
library should we use?The sad truth is that there are no well-maintained libs in the ecosystem.
Never the less it is not hard to maintain something just for strawberry since the implementation
is rather straight forward and not much features are needed. we can fork either
and just forget about it.
then strawberry could use that and you could use whatever you want.
The text was updated successfully, but these errors were encountered: