Repository: pydantic/pydantic

Issue:
create_model_from_typeddict reports a type error when given the correct input type
### Checks

* [x ] I added a descriptive title to this issue
* [x ] I have searched (google, github) for similar issues and couldn't find anything
* [x ] I have read and followed [the docs](https://pydantic-docs.helpmanual.io/) and still think this is a bug

<!-- Sorry to sound so draconian, but every second saved replying to issues is time spend improving pydantic :-) -->

# Bug

When running mypy using create_model_from_typeddict() I get a type error for the input - the code however works as expected. When I run the code below, using `mypy myscript.py`, I get the following error.

```
error: Argument 1 to "create_model_from_typeddict" has incompatible type "Type[SomeDict]"; expected "Type[TypedDict]"
```

Output of `python -c "import pydantic.utils; print(pydantic.utils.version_info())"`:
```
pydantic version: 1.8.2
pydantic compiled: True
install path: /Users/lewiswolstanholme/.local/share/virtualenvs/drum-shape- 
predictor-YZkKhtr_/lib/python3.9/site-packages/pydantic
python version: 3.9.6 (default, Jun 29 2021, 06:20:32)  [Clang 12.0.0 (clang-1200.0.32.29)]
platform: macOS-10.15.7-x86_64-i386-64bit
optional deps. installed: ['typing-extensions']
```
<!-- or if you're using pydantic prior to v1.3, manually include: OS, python version and pydantic version -->

<!-- Please read the [docs](https://pydantic-docs.helpmanual.io/) and search through issues to
confirm your bug hasn't already been reported. -->

<!-- Where possible please include a self-contained code snippet describing your bug: -->

```py
from typing import TypedDict 
import pydantic


class SomeDict(TypedDict):
    val: int
    name: str

# this could be a valid/invalid declaration
obj: SomeDict = {
    'val': 12,
    'name': 'John',
}

# validate with pydantic
try:
    pydantic.create_model_from_typeddict(SomeDict)(**obj)

except pydantic.ValidationError as exc: 
    print(f"ERROR: Invalid schema: {exc}")
```



Discussion:

Resolving patch:
diff --git a/pydantic/annotated_types.py b/pydantic/annotated_types.py
--- a/pydantic/annotated_types.py
+++ b/pydantic/annotated_types.py
@@ -4,15 +4,14 @@
 from .main import BaseModel, create_model
 
 if TYPE_CHECKING:
+    from typing_extensions import TypedDict
 
-    class TypedDict(Dict[str, Any]):
-        __annotations__: Dict[str, Type[Any]]
-        __total__: bool
-        __required_keys__: FrozenSet[str]
-        __optional_keys__: FrozenSet[str]
 
-
-def create_model_from_typeddict(typeddict_cls: Type['TypedDict'], **kwargs: Any) -> Type['BaseModel']:
+def create_model_from_typeddict(
+    # Mypy bug: `Type[TypedDict]` is resolved as `Any` https://github.com/python/mypy/issues/11030
+    typeddict_cls: Type['TypedDict'],  # type: ignore[valid-type]
+    **kwargs: Any,
+) -> Type['BaseModel']:
     """
     Create a `BaseModel` based on the fields of a `TypedDict`.
     Since `typing.TypedDict` in Python 3.8 does not store runtime information about optional keys,
@@ -27,8 +26,9 @@ def create_model_from_typeddict(typeddict_cls: Type['TypedDict'], **kwargs: Any)
             'Without it, there is no way to differentiate required and optional fields when subclassed.'
         )
 
+    required_keys: FrozenSet[str] = typeddict_cls.__required_keys__  # type: ignore[attr-defined]
     field_definitions = {
-        field_name: (field_type, Required if field_name in typeddict_cls.__required_keys__ else None)
+        field_name: (field_type, Required if field_name in required_keys else None)
         for field_name, field_type in typeddict_cls.__annotations__.items()
     }
 
diff --git a/pydantic/validators.py b/pydantic/validators.py
--- a/pydantic/validators.py
+++ b/pydantic/validators.py
@@ -26,8 +26,6 @@
 )
 from uuid import UUID
 
-from typing_extensions import Literal
-
 from . import errors
 from .datetime_parse import parse_date, parse_datetime, parse_duration, parse_time
 from .typing import (
@@ -45,7 +43,8 @@
 from .utils import almost_equal_floats, lenient_issubclass, sequence_like
 
 if TYPE_CHECKING:
-    from .annotated_types import TypedDict
+    from typing_extensions import Literal, TypedDict
+
     from .config import BaseConfig
     from .fields import ModelField
     from .types import ConstrainedDecimal, ConstrainedFloat, ConstrainedInt
@@ -576,14 +575,14 @@ def namedtuple_validator(values: Tuple[Any, ...]) -> NamedTupleT:
 
 
 def make_typeddict_validator(
-    typeddict_cls: Type['TypedDict'], config: Type['BaseConfig']
+    typeddict_cls: Type['TypedDict'], config: Type['BaseConfig']  # type: ignore[valid-type]
 ) -> Callable[[Any], Dict[str, Any]]:
     from .annotated_types import create_model_from_typeddict
 
     TypedDictModel = create_model_from_typeddict(typeddict_cls, __config__=config)
     typeddict_cls.__pydantic_model__ = TypedDictModel  # type: ignore[attr-defined]
 
-    def typeddict_validator(values: 'TypedDict') -> Dict[str, Any]:
+    def typeddict_validator(values: 'TypedDict') -> Dict[str, Any]:  # type: ignore[valid-type]
         return TypedDictModel.parse_obj(values).dict(exclude_unset=True)
 
     return typeddict_validator


Test patch:
diff --git a/tests/mypy/modules/success.py b/tests/mypy/modules/success.py
--- a/tests/mypy/modules/success.py
+++ b/tests/mypy/modules/success.py
@@ -11,6 +11,8 @@
 from typing import Any, Dict, Generic, List, Optional, TypeVar
 from uuid import UUID
 
+from typing_extensions import TypedDict
+
 from pydantic import (
     UUID1,
     BaseConfig,
@@ -38,6 +40,7 @@
     StrictInt,
     StrictStr,
     create_model,
+    create_model_from_typeddict,
     root_validator,
     validate_arguments,
     validator,
@@ -245,7 +248,16 @@ class Config:
 validated.my_dir_path.absolute()
 validated.my_dir_path_str.absolute()
 
-DynamicModel = create_model('DynamicModel')
+
+class SomeDict(TypedDict):
+    val: int
+    name: str
+
+
+obj: SomeDict = {
+    'val': 12,
+    'name': 'John',
+}
 
 
 class Config(BaseConfig):
@@ -269,3 +281,7 @@ def __fspath__(self) -> str:
 def dont_check_path_existence() -> None:
     Settings(_env_file='a/path', _secrets_dir='a/path')
     Settings(_env_file=CustomPath('a/path'), _secrets_dir=CustomPath('a/path'))
+
+
+create_model_from_typeddict(SomeDict)(**obj)
+DynamicModel = create_model('DynamicModel')