Mypy allowing `List[str]` to have values of type `Tuple[str, List[str]]`

Viewed 349

The following minified example was originally found while making changes to my work's code base. I have the line x: List[str] = [] so I expect that mypy will enforce that, but in this example it seems it does not. If I want mypy to catch this, what should I do differently?

from typing import List

x: List[str] = []
y = ["world"]
z = ["hello"]

def go(boop):
    return f"{boop}!", y

x = list(map(go, z))
print(x)

# output:
# [('hello!', ['world'])]
$ mypy mypy_lists.py   
Success: no issues found in 1 source file
$ python3 mypy_lists.py
[('hello!', ['world'])]

EDIT:

For context, the , y part of the definition of go was a copy-paste error, and I expected to be protected against that by just the x: List[str] annotation, but maybe I have to update my internal model of mypy type checking, and just trust it less.

EDIT 2:

Given the accepted answer, the amount I can trust mypy with type hints seems to be directly related to the way mypy is configured. Not terribly surprising, but a good thing to remember.

2 Answers

It seems that adding type annotations to the go function causes mypy to correctly pick up on the problem:

$ mypy -c 'from typing import List, Tuple

x: List[str] = []
y = ["world"]
z = ["hello"]

def go(boop: str) -> Tuple[str, List[str]]:
    return f"{boop}!", y

x = list(map(go, z))
print(x)'
<string>:10: error: Argument 1 to "map" has incompatible type "Callable[[Any], Tuple[str, List[str]]]"; expected "Callable[[str], str]"
Found 1 error in 1 file (checked 1 source file)

By default mypy ignores untyped function definitions.

This helps gradually introduce type annotations into an existing codebase without having to add them all at once.

Personally for new projects I run mypy with the --strict option to avoid accidentally leaving functions unannotated and bypassing type checks.

Related