python / python/mypy

DefaultDict of a TypedDict confuses mypy

Open
#7,217 4 comments 6 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug false-positive priority-1-normal topic-typed-dict
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

image

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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.