DefaultDict of a TypedDict confuses mypy
Hi 👋 ! I have the following test code:
from collections import defaultdict
from typing import DefaultDict
from mypy_extensions import TypedDict
RepoPath = str
RepoStatus = TypedDict('RepoStatus', {
'branch': str,
'remote': str,
'clean': bool,
# ...
}, total=False)
State2 = defaultdict(RepoStatus) # type: DefaultDict[RepoPath, RepoStatus]
State3 = defaultdict(dict) # type: DefaultDict[RepoPath, RepoStatus]
State4 = defaultdict(lambda: RepoStatus()) # type: DefaultDict[RepoPath, RepoStatus]
State5 = defaultdict(lambda: dict()) # type: DefaultDict[RepoPath, RepoStatus]
State6 = defaultdict(lambda: {}) # type: DefaultDict[RepoPath, RepoStatus]
mypy only accepts the definition of 4 and 6. A pic is easy to follow here

mypy output:
16:10 error mypy Argument 1 to "defaultdict" has incompatible type "Type[RepoStatus]"; expected
"Optional[Callable[[], RepoStatus]]"
17:10 error mypy Argument 1 to "defaultdict" has incompatible type "Type[Dict[Any, Any]]";
expected "Optional[Callable[[], RepoStatus]]"
19:10 error mypy Argument 1 to "defaultdict" has incompatible type "Callable[[], Dict[<nothing>,
<nothing>]]"; expected "Optional[Callable[[], RepoStatus]]"
19:22 error mypy Incompatible return value type (got "Dict[<nothing>, <nothing>]", expected
"RepoStatus")
Ideally the def of State3, just defaultdict(dict), should work, shouldn't it? It is also very surprising that there is a difference between 5 and 6.
mypy 0.720
Yeah, it would be nice if all the cases would be supported by mypy. I think that at least case 5 could be easy to support. 2 and 3 might be harder or require more ad hoc changes.
And thanks for the detailed report!
Hello there, any update on this issue? Thank you very much.
There is no error message for State5 now.
I just checked that with my PR https://github.com/python/mypy/pull/19254 everything except State3 works (that one will require some hardcore special-casing probably).