Repository: strawberry-graphql/strawberry

Issue:
TypeError: Forward references must evaluate to types.
So I am running Strawberry with Fastapi

## Describe the Bug

I have a schema like this:

```
from __future__ import annotations
from enum import Enum
import strawberry
import datetime
from strawberry.scalars import JSON

@strawberry.enum
class Sex(Enum):
    male = "Male"
    female ="Female"

@strawberry.type
class PersonBase:
    name: JSON | None
    sex: Sex | None

@strawberry.type
class Client(PersonBase):
    firm: Firm | None = None


```
 When I try to run the server it throws back an error:

```
  File "C:\Users\0\Desktop\Fastapi\Test\.\app\main.py", line 14, in <module>
    from app.schema import schema
  File "C:\Users\0\Desktop\Fastapi\Test\.\app\schema.py", line 624, in <module>
    schema = strawberry.Schema(query=Query, mutation = Mutation)
  File "C:\Users\0\Envs\Fastapi\lib\site-packages\strawberry\schema\schema.py", line 115, in __init__
    self._schema = GraphQLSchema(
  File "C:\Users\0\Envs\Fastapi\lib\site-packages\graphql\type\schema.py", line 224, in __init__
    collect_referenced_types(query)
  File "C:\Users\0\Envs\Fastapi\lib\site-packages\graphql\type\schema.py", line 433, in collect_referenced_types
    collect_referenced_types(field.type)
  File "C:\Users\0\Envs\Fastapi\lib\site-packages\graphql\type\schema.py", line 433, in collect_referenced_types
    collect_referenced_types(field.type)
  File "C:\Users\0\Envs\Fastapi\lib\site-packages\graphql\type\schema.py", line 432, in collect_referenced_types
    for field in named_type.fields.values():
  File "C:\Users\0\AppData\Local\Programs\Python\Python310\lib\functools.py", line 970, in __get__
    val = self.func(instance)
  File "C:\Users\0\Envs\Fastapi\lib\site-packages\graphql\type\definition.py", line 811, in fields
    raise cls(f"{self.name} fields cannot be resolved. {error}") from error
TypeError: Client fields cannot be resolved. Forward references must evaluate to types. Got <strawberry.type.StrawberryOptional object at 0x000002C85C5F5990>.
```
Note that if I change one thing like this making a required name field with a string the error is resolved

```
@strawberry.type
class Client(PersonBase):
    firm: Firm | None = None
    name: str | None
```

But if I put PersonBase into the model like this, it still throws an error even though the name field is required as JSON.

```
class Client:
    firm: Firm | None = None
    name: JSON | None
    sex: Sex | None
```


## System Information

 - Operating system: Windows 10
 - Strawberry version (if applicable): strawberry-graphql==0.139.0

## Additional Context

Not sure if this is an bug or I did something wrong but I find this behavior strange because the JSON and Enum are both scalars but required and they triggered a type error.


<!-- POLAR PLEDGE BADGE START -->
## Upvote & Fund

- We're using [Polar.sh](https://polar.sh/strawberry-graphql) so you can upvote and help fund this issue.
- We receive the funding once the issue is completed & confirmed by you.
- Thank you in advance for helping prioritize & fund our backlog.

<a href="https://polar.sh/strawberry-graphql/strawberry/issues/2465">
<picture>
  <source media="(prefers-color-scheme: dark)" srcset="https://polar.sh/api/github/strawberry-graphql/strawberry/issues/2465/pledge.svg?darkmode=1">
  <img alt="Fund with Polar" src="https://polar.sh/api/github/strawberry-graphql/strawberry/issues/2465/pledge.svg">
</picture>
</a>
<!-- POLAR PLEDGE BADGE END -->



Discussion:
@ccsv I was able to work around a similar issue with an optional union by specifying the field explicitly with a separate GraphQL type:

```py
# Python type used by type checkers
Foo = Union[Bar, Baz, None]

@strawberry.type
class Biff:
   foo: Foo = strawberry.field(
       # GraphQL type used by Strawberry
       graphql_type=strawberry.union([Bar, Baz]) | None
   )
```

I think that this is because an expression like `strawberry.union([...]) | None` results in a `StrawberryOptional` object that isn't a `type`, so not valid in a type annotation.
@twm that should not be the case because by default you have a `id` field that is a type. It seems weird that you cannot have a required `scalar` field only.
Hey @ccsv . I tried reproducing your issue but wasn't able to. What version of python are you using? I tested using python 3.11
@bellini666 the path in their error output contains `\Python310\lib`, which I can confirm - strawberry code using a `scalar | None` field works fine on 3.11 but fails with this error on 3.10.
Confirming this error occurs on 3.10, seemingly any time I type a field as `<some_custom_scalar> | None`.

The error does not occur if the type is `Optional[<some_custom_scalar>]`, even though this should be equivalent.
@linusg @sirrus233 do you mean that only happens for custom scalars? i.e. if you do `str | None` it works but not with `JSON | None` on python 3.10 only?
That is correct. I can confirm `str | None`, `int | None`, and `bool | None` all work without any problems.

Resolving patch:
diff --git a/strawberry/custom_scalar.py b/strawberry/custom_scalar.py
--- a/strawberry/custom_scalar.py
+++ b/strawberry/custom_scalar.py
@@ -17,7 +17,7 @@
 )
 
 from strawberry.exceptions import InvalidUnionTypeError
-from strawberry.type import StrawberryOptional, StrawberryType
+from strawberry.type import StrawberryType
 
 from .utils.str_converters import to_camel_case
 
@@ -76,7 +76,7 @@ def __call__(self, *args: str, **kwargs: Any):
     def __or__(self, other: Union[StrawberryType, type]) -> StrawberryType:
         if other is None:
             # Return the correct notation when using `StrawberryUnion | None`.
-            return StrawberryOptional(of_type=self)
+            return Optional[self]
 
         # Raise an error in any other case.
         # There is Work in progress to deal with more merging cases, see:


Test patch:
diff --git a/tests/test_forward_references.py b/tests/test_forward_references.py
--- a/tests/test_forward_references.py
+++ b/tests/test_forward_references.py
@@ -10,6 +10,7 @@
 
 import strawberry
 from strawberry.printer import print_schema
+from strawberry.scalars import JSON
 from strawberry.type import StrawberryList, StrawberryOptional
 
 
@@ -23,16 +24,25 @@ class Query:
     @strawberry.type
     class MyType:
         id: strawberry.ID
+        scalar: JSON
+        optional_scalar: JSON | None
+
+    expected_representation = '''
+    """
+    The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf).
+    """
+    scalar JSON @specifiedBy(url: "http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf")
 
-    expected_representation = """
     type MyType {
       id: ID!
+      scalar: JSON!
+      optionalScalar: JSON
     }
 
     type Query {
       myself: MyType!
     }
-    """
+    '''
 
     schema = strawberry.Schema(Query)
 
diff --git a/tests/utils/test_typing_forward_refs.py b/tests/utils/test_typing_forward_refs.py
--- a/tests/utils/test_typing_forward_refs.py
+++ b/tests/utils/test_typing_forward_refs.py
@@ -5,6 +5,7 @@
 
 import pytest
 
+from strawberry.scalars import JSON
 from strawberry.utils.typing import eval_type
 
 
@@ -26,6 +27,7 @@ class Foo:
         eval_type(ForwardRef("List[Foo | str] | None | int"), globals(), locals())
         == Union[List[Union[Foo, str]], int, None]
     )
+    assert eval_type(ForwardRef("JSON | None"), globals(), locals()) == Optional[JSON]
 
 
 @pytest.mark.skipif(