Repository: pydantic/pydantic

Issue:
`NotRequired` receives `(T,)` instead of `T` in Generic TypedDict
### Initial Checks

- [X] I confirm that I'm using Pydantic V2

### Description

Pydantic seems to resolve the Generic in a TypedDict as a tuple value for NotRequired and Required, which only accepts single types. `(str,)` should become `str`.

```py
Traceback (most recent call last):
  File "test.py", line 18, in <module>
    FooWithStrAdapter = TypeAdapter(FooWithStr)
... # truncated error
  File "env/lib/python3.10/site-packages/pydantic/_internal/_generate_schema.py", line 830, in _match_generic_type
    return self._typed_dict_schema(obj, origin)
  File "env/lib/python3.10/site-packages/pydantic/_internal/_generate_schema.py", line 1097, in _typed_dict_schema
    annotation = replace_types(annotation, typevars_map)
  File "env/lib/python3.10/site-packages/pydantic/_internal/_generics.py", line 314, in replace_types
    return origin_type[resolved_type_args]
  File "/opt/conda/envs/py310/lib/python3.10/typing.py", line 312, in inner
    return func(*args, **kwds)
  File "/opt/conda/envs/py310/lib/python3.10/typing.py", line 403, in __getitem__
    return self._getitem(self, parameters)
  File "env/lib/python3.10/site-packages/typing_extensions.py", line 1884, in NotRequired
    item = typing._type_check(parameters, f'{self._name} accepts only a single type.')
  File "/opt/conda/envs/py310/lib/python3.10/typing.py", line 176, in _type_check
    raise TypeError(f"{msg} Got {arg!r:.100}.")
TypeError: NotRequired accepts only a single type. Got (<class 'str'>,).
```

### Example Code

```Python
from typing_extensions import TypedDict, TypeVar, NotRequired, Generic
from pydantic import TypeAdapter

T = TypeVar("T")


class FooStr(TypedDict):
    type: NotRequired[str]


class FooGeneric(TypedDict, Generic[T]):
    type: NotRequired[T]


FooWithStr = FooGeneric[str]

FooStrAdapter = TypeAdapter(FooStr) # passes
FooWithStrAdapter = TypeAdapter(FooWithStr) # fails
```


### Python, Pydantic & OS Version

```Text
pydantic version: 2.4.2
        pydantic-core version: 2.10.1
          pydantic-core build: profile=release pgo=true
                 install path: env/lib/python3.10/site-packages/pydantic
               python version: 3.10.5 | packaged by conda-forge | (main, Jun 14 2022, 07:06:46) [GCC 10.3.0]
                     platform: Linux
             related packages: typing_extensions-4.8.0 fastapi-0.104.0
```



Discussion:
Hi @NCPlayz,

Thanks for reporting this. This does look like a bug. I'll have a fix up shortly 🐛 🔨 !

Resolving patch:
diff --git a/pydantic/_internal/_generics.py b/pydantic/_internal/_generics.py
--- a/pydantic/_internal/_generics.py
+++ b/pydantic/_internal/_generics.py
@@ -311,7 +311,8 @@ def replace_types(type_: Any, type_map: Mapping[Any, Any] | None) -> Any:
         # We also cannot use isinstance() since we have to compare types.
         if sys.version_info >= (3, 10) and origin_type is types.UnionType:
             return _UnionGenericAlias(origin_type, resolved_type_args)
-        return origin_type[resolved_type_args]
+        # NotRequired[T] and Required[T] don't support tuple type resolved_type_args, hence the condition below
+        return origin_type[resolved_type_args[0] if len(resolved_type_args) == 1 else resolved_type_args]
 
     # We handle pydantic generic models separately as they don't have the same
     # semantics as "typing" classes or generic aliases


Test patch:
diff --git a/tests/test_generics.py b/tests/test_generics.py
--- a/tests/test_generics.py
+++ b/tests/test_generics.py
@@ -35,8 +35,10 @@
 from typing_extensions import (
     Annotated,
     Literal,
+    NotRequired,
     OrderedDict,
     ParamSpec,
+    TypedDict,
     TypeVarTuple,
     Unpack,
     get_args,
@@ -53,6 +55,7 @@
     PositiveInt,
     PydanticSchemaGenerationError,
     PydanticUserError,
+    TypeAdapter,
     ValidationError,
     ValidationInfo,
     computed_field,
@@ -2849,3 +2852,20 @@ def test_mix_default_and_constraints() -> None:
 
         class _(BaseModel, Generic[T]):
             x: T
+
+
+def test_generic_with_not_required_in_typed_dict() -> None:
+    T = TypingExtensionsTypeVar('T')
+
+    class FooStr(TypedDict):
+        type: NotRequired[str]
+
+    class FooGeneric(TypedDict, Generic[T]):
+        type: NotRequired[T]
+
+    ta_foo_str = TypeAdapter(FooStr)
+    assert ta_foo_str.validate_python({'type': 'tomato'}) == {'type': 'tomato'}
+    assert ta_foo_str.validate_python({}) == {}
+    ta_foo_generic = TypeAdapter(FooGeneric[str])
+    assert ta_foo_generic.validate_python({'type': 'tomato'}) == {'type': 'tomato'}
+    assert ta_foo_generic.validate_python({}) == {}