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

Upvotes: 1

Views: 893

Answers (1)

Samwise
Samwise

Reputation: 71542

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).

Upvotes: 4

Related Questions