python / python/mypy

Dict's .get() method doesn't limit possible types of the given element

Open
#12,457 4 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

feature priority-2-low topic-type-narrowing
Dominant language
Python
Stars
20.6k
Forks
3.3k
PR merge metrics
PR metrics pending

Description

Bug Report

from typing import Optional, Dict

def test(arg: str) -> None:
    ...

def this_fails(arg: Dict[str, Optional[str]]) -> None:
    if arg.get("key") is not None:
       test(arg["key"])  # error

def this_fails_also(arg: Dict[str, Optional[str]]) -> None:
    if arg.get("key") is not None:
       test(arg.get("key"))  # error

def but_this_pass(arg: Dict[str, Optional[str]]) -> None:
    if arg.get("key") and arg["key"] is not None:
        test(arg["key"])

def this_pass_also_but_is_unsafe(arg: Dict[str, Optional[str]]) -> None:
    if arg["key"] is not None:
        test(arg["key"])

First two methods fail due to Argument 1 to "test" has incompatible type "Optional[str]"; expected "str" error.
Mypy seems to see no relation between arg["key"] and arg.get("key") and it should (IMHO).
I'm not sure if this is a bug and not a feature request, but arg.get("key") and arg["key"] is not None looks redundant for me.

Expected Behavior
The possibility of arg["key"] is None should be excluded by if arg.get("key") is not None because the inner block is unreachable if "key in arg and arg["key"] is None so the value is no longer Optional.

Environment
mypy 0.942
Python 3.10.0

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

Reproduce the two failing examples and the passing comparisons from the issue using mypy 0.942 and Python 3.10. Investigate how type narrowing relates values returned by Dict.get() to indexed lookups, and consider the work complete when the reported safe pattern narrows the value to str without accepting the unsafe case.

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
Clearly specified
Newbie friendliness
40/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.