DefaultDict of a TypedDict confuses mypy
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 20.6k
- Forks
- 3.3k
- PR merge metrics
- PR metrics pending
Description
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
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the issue's State2–State6 snippet with mypy 0.720 and compare the diagnostics for each defaultdict form. Trace how defaultdict constructor arguments and TypedDict return types are inferred; done means the intended forms type-check consistently and the unexpected difference between State5 and State6 is resolved or documented by tests.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100