Search code examples
pythonmypy

Type-hinting problem with mypy when iterating through a list of arguments


Here is a MRE:

def test(a: int | tuple[int, int]):
    print(a)


if __name__ == "__main__":
    for b in [1, (1, 2)]:
        test(b)

mypy outputs: 7: error: Argument 1 to "test" has incompatible type "object"; expected "Union[int, Tuple[int, int]]" [arg-type]

But I'm passing to the function func an integer and a tuple of two integers, hence why I don't understand the error.

I'm using:

platform win32 -- Python 3.11.1, pytest-7.2.0, pluggy-1.0.0
plugins: anyio-3.6.2, mypy-0.10.3

Solution

  • Mypy is inferring the type of [1, (1, 2)] as list[object] (since that's the common denominator of the types in the list); it doesn't automatically infer union types.

    The best solution I can think of is to explicitly declare the type of the list by giving it a name and annotation:

    if __name__ == "__main__":
        a: list[int | tuple[int, int]] = [1, (1, 2)]
        for b in a:
            test(b)
    

    but I would suggest examining the real-world context where you're hitting this situation and see if you can avoid having a list of mixed types in the first place (this is IMO a smell that the data isn't organized in the most effective way).