Repository: strawberry-graphql/strawberry

Issue:
`FieldExtension` changes to return type aren't reflected in schema
## Describe the Bug

Since upgrading to latest Strawberry, `FieldExtension`s don't appear to be able to modify the return type (`.type`) of a field.

I've attached a code sample to reproduce:
```python
import strawberry
from strawberry.annotation import StrawberryAnnotation
from strawberry.field import StrawberryField
from strawberry.extensions import FieldExtension


class ChangeReturnTypeExtension(FieldExtension):
    def apply(self, field: StrawberryField) -> None:
        print(f'Converting field return type to int... (Currently: {field.type} / {field.type_annotation.resolve()})')
        field.type_annotation = StrawberryAnnotation.from_annotation(int)
        field.type = int
        print(f'Done. (New type: {field.type} / {field.type_annotation.resolve()})')

    # Not part of the example, needed so Strawberry can resolve
    def resolve(self, next_, source, info, **kwargs):
        return next_(source, info, **kwargs)


@strawberry.type
class Query:
    @strawberry.field(extensions=[ChangeReturnTypeExtension()])
    def test_changing_return_type(self) -> bool:
        # doesn't matter that type checkers complain - this is just to see the field type
        return 1


schema = strawberry.Schema(query=Query)
```

Run with `strawberry server main:schema`.

When ran on my laptop, this is the output:

```
$ strawberry server main:schema
Converting field return type to int... (Currently: <class 'bool'> / <class 'bool'>)
Done. (New type: <class 'int'> / <class 'int'>)
Running strawberry on http://0.0.0.0:8000/graphql 🍓
Converting field return type to int... (Currently: <class 'bool'> / <class 'bool'>)
Done. (New type: <class 'int'> / <class 'int'>)
Converting field return type to int... (Currently: <class 'bool'> / <class 'bool'>)
Done. (New type: <class 'int'> / <class 'int'>)
```

This _appears_ to successfully change the field's return type from a `bool` to an `int`. I've tried updating `field.type` and `field.type_annotation` together, and also each one independently. In previous versions of Strawberry, updating just `field.type_annotation` as shown above worked.

Checking field.type/type_annotation immediately after updating it does appear to show the new type - however the GraphQL schema won't actually reflect this. I've attached a screenshot of GraphiQL when running the above sample code.

![image](https://github.com/strawberry-graphql/strawberry/assets/1781217/4521bfec-2890-47d2-84b0-821834e32fd9)

I'm not sure if updating a field's type in a `FieldExtension` is officially supported behavior, but regardless it appears to be a regression compared to previous versions.

## System Information

 - Operating system: macOS / Python 3.10
 - Strawberry version (if applicable): `0.193.0`


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



Discussion:

Resolving patch:
diff --git a/strawberry/schema/schema_converter.py b/strawberry/schema/schema_converter.py
--- a/strawberry/schema/schema_converter.py
+++ b/strawberry/schema/schema_converter.py
@@ -56,7 +56,6 @@
     StrawberryList,
     StrawberryOptional,
     StrawberryType,
-    WithStrawberryObjectDefinition,
     has_object_definition,
 )
 from strawberry.types.info import Info
@@ -99,9 +98,7 @@ def __call__(  # pragma: no cover
         self,
         field: StrawberryField,
         *,
-        override_type: Optional[
-            Union[StrawberryType, Type[WithStrawberryObjectDefinition]]
-        ] = None,
+        type_definition: Optional[StrawberryObjectDefinition] = None,
     ) -> FieldType:
         ...
 
@@ -125,7 +122,7 @@ def _get_thunk_mapping(
     thunk_mapping: Dict[str, FieldType] = {}
 
     for field in type_definition.fields:
-        field_type = field.resolve_type(type_definition=type_definition)
+        field_type = field.type
 
         if field_type is UNRESOLVED:
             raise UnresolvedFieldTypeError(type_definition, field)
@@ -133,7 +130,7 @@ def _get_thunk_mapping(
         if not is_private(field_type):
             thunk_mapping[name_converter(field)] = field_converter(
                 field,
-                override_type=field_type,
+                type_definition=type_definition,
             )
 
     return thunk_mapping
@@ -305,15 +302,16 @@ def from_field(
         self,
         field: StrawberryField,
         *,
-        override_type: Optional[
-            Union[StrawberryType, Type[WithStrawberryObjectDefinition]]
-        ] = None,
+        type_definition: Optional[StrawberryObjectDefinition] = None,
     ) -> GraphQLField:
         # self.from_resolver needs to be called before accessing field.type because
         # in there a field extension might want to change the type during its apply
         resolver = self.from_resolver(field)
         field_type = cast(
-            "GraphQLOutputType", self.from_maybe_optional(override_type or field.type)
+            "GraphQLOutputType",
+            self.from_maybe_optional(
+                field.resolve_type(type_definition=type_definition)
+            ),
         )
         subscribe = None
 
@@ -342,12 +340,13 @@ def from_input_field(
         self,
         field: StrawberryField,
         *,
-        override_type: Optional[
-            Union[StrawberryType, Type[WithStrawberryObjectDefinition]]
-        ] = None,
+        type_definition: Optional[StrawberryObjectDefinition] = None,
     ) -> GraphQLInputField:
         field_type = cast(
-            "GraphQLInputType", self.from_maybe_optional(override_type or field.type)
+            "GraphQLInputType",
+            self.from_maybe_optional(
+                field.resolve_type(type_definition=type_definition)
+            ),
         )
         default_value: object
 


Test patch:
diff --git a/tests/fields/test_field_exceptions.py b/tests/fields/test_field_exceptions.py
--- a/tests/fields/test_field_exceptions.py
+++ b/tests/fields/test_field_exceptions.py
@@ -1,10 +1,16 @@
+import textwrap
+from typing import Any
+
 import pytest
 
 import strawberry
+from strawberry.annotation import StrawberryAnnotation
 from strawberry.exceptions import (
     FieldWithResolverAndDefaultFactoryError,
     FieldWithResolverAndDefaultValueError,
 )
+from strawberry.extensions.field_extension import FieldExtension
+from strawberry.field import StrawberryField
 
 
 def test_field_with_resolver_default():
@@ -36,3 +42,28 @@ class Query:
             @strawberry.field(default_factory=lambda: "steel")
             def metal(self) -> str:
                 return "iron"
+
+
+def test_extension_changing_field_return_value():
+    """Ensure that field extensions can change the field's return type."""
+
+    class ChangeReturnTypeExtension(FieldExtension):
+        def apply(self, field: StrawberryField) -> None:
+            field.type_annotation = StrawberryAnnotation.from_annotation(int)
+
+        def resolve(self, next_, source, info, **kwargs: Any):
+            return next_(source, info, **kwargs)
+
+    @strawberry.type
+    class Query:
+        @strawberry.field(extensions=[ChangeReturnTypeExtension()])
+        def test_changing_return_type(self) -> bool:
+            ...
+
+    schema = strawberry.Schema(query=Query)
+    expected = """\
+      type Query {
+        testChangingReturnType: Int!
+      }
+    """
+    assert str(schema) == textwrap.dedent(expected).strip()