Repository: strawberry-graphql/strawberry

Issue:
Error validating return types when using a Generic in Union
There seems to be an issue with types.
Generics worked fine and dandy until I've tried to use them in a Union.

```python
@strawberry.type
class FaultyType:
    code_sent: bool
    result: Union[Pet, ErrorNode[Codes]]
```
Here returning an ErrorNode in "result" field fails type check.
Fails with strawberry.exceptions.UnallowedReturnTypeForUnion: The type "<class 'strawberry_sample.ErrorNode'>" of the field "result" is not in the list of the types of the union: "['CodesErrorNode', 'Pet']"

Returning the same generic without unions in type declaration works fine.

Full sample:
https://gist.github.com/MeRuslan/5bd179f28fc5ae05e815429ee02ebdf6


Discussion:
Might be helpful: this also fails in the same way when generic type is just a field of parent type in union.

```
@strawberry.type
class ErrorWithData(Generic[DataType]):
     code: str
     data: DataType

@strawberry.type
class MessageOnlyErrorData:
     message: str

ErrorWithMessage = ErrorWithData[MessageOnlyErrorData]

@strawberry.type
class ErrorResponse:  # Not a generic type, but has a field with generic type
     error: ErrorWithMessage # generic type

@strawberry.type
class FaultyType:
    code_sent: bool
    result: Union[Pet, ErrorWithMessage]
```

I did quick check, and it looks like it was introduced in https://github.com/strawberry-graphql/strawberry/blob/main/CHANGELOG.md#0690---2021-07-20 .

Version 0.68.4 does work for me and 0.69.4 does not :blush: 
Okay, the problem is in how internal type checks are performed.
The problem arises from the fact that enums are wrapped in an EnumDefinition when used in a generic typevar.

But the returned value is checked as is, with no preprocessing, and obviously the types do not match.
When using a strawberry type instead of an enum, everything checks out, ie
```python
@strawberry.type
class FaultyType:
    code_sent: bool
    result: Union[Pet, ErrorNode[NotAnEnumType]]
```
The failing check is at types.py -> TypeDefinition.is_implemented_by of a generic type that has an enum as its typevar.

Where exactly to rectify the problem I don't currently fully understand, which is the root problem here:
1. EnumDefinition getting passed as an expected type
2. Checks not being elaborate enough

Feels like the first is the problem.
@jkimbo @patrick91 helping hand needed.
Hello..
Hey, this somehow slipped past my attention. I'll take a look at this tonight to see what's up.

Resolving patch:
diff --git a/strawberry/types/types.py b/strawberry/types/types.py
--- a/strawberry/types/types.py
+++ b/strawberry/types/types.py
@@ -152,6 +152,13 @@ def is_implemented_by(self, root: Union[type, dict]) -> bool:
 
             # Check if the expected type matches the type found on the type_map
             real_concrete_type = type(getattr(root, generic_field.name))
+
+            # TODO: uniform type var map, at the moment we map object types
+            # to their class (not to TypeDefinition) while we map enum to
+            # the EnumDefinition class. This is why we do this check here:
+            if hasattr(real_concrete_type, "_enum_definition"):
+                real_concrete_type = real_concrete_type._enum_definition
+
             if real_concrete_type is not expected_concrete_type:
                 return False
 


Test patch:
diff --git a/tests/schema/test_generics.py b/tests/schema/test_generics.py
--- a/tests/schema/test_generics.py
+++ b/tests/schema/test_generics.py
@@ -1,5 +1,6 @@
 import textwrap
 import typing
+from enum import Enum
 
 import pytest
 
@@ -352,6 +353,45 @@ def example(self) -> typing.Union[Fallback, Edge[int]]:
     }
 
 
+def test_generic_with_enum_as_param_of_type_inside_unions():
+    T = typing.TypeVar("T")
+
+    @strawberry.type
+    class Pet:
+        name: str
+
+    @strawberry.type
+    class ErrorNode(typing.Generic[T]):
+        code: T
+
+    @strawberry.enum
+    class Codes(Enum):
+        a = "a"
+        b = "b"
+
+    @strawberry.type
+    class Query:
+        @strawberry.field
+        def result(self) -> typing.Union[Pet, ErrorNode[Codes]]:
+            return ErrorNode(code=Codes.a)
+
+    schema = strawberry.Schema(query=Query)
+
+    query = """{
+        result {
+            __typename
+            ... on CodesErrorNode {
+                code
+            }
+        }
+    }"""
+
+    result = schema.execute_sync(query)
+
+    assert not result.errors
+    assert result.data == {"result": {"__typename": "CodesErrorNode", "code": "a"}}
+
+
 def test_supports_generic_in_unions_multiple_vars():
     A = typing.TypeVar("A")
     B = typing.TypeVar("B")