How to correctly assign elements of recursively typed collections?

36 Views Asked by At

According to https://github.com/python/mypy/issues/731 recursive type definition should be possible and enabled by default. And for me it's working somehow.

However I didn't manage to successfully assign a value from a recursively typed list, without mypy complaining:

from typing import Union  # need this, because strings cannot be `or`-ed

NestedStringSequence = list[Union[str, "NestedStringSequence"]]

element: NestedStringSequence = []
stack: NestedStringSequence = [element]

stack.append([])
element = stack.pop()

So element should be str or NestedStringSequence, yet mypy gives me

$ mypy nested.py
nested.py:10: error: Incompatible types in assignment (expression has type "Union[str, NestedStringSequence]", variable has type "NestedStringSequence")  [assignment]
Found 1 error in 1 file (checked 1 source file)

.. which sounds like a contradiction to me because NestedStringSequence is by definition Union[str, NestedStringSequence]

But of course it's not a contradiction - stack.pop() could return a str, and only I know that I'm only appending lists..

How should I deal with this? I could cast the result of stack.pop() of course, but that would be cheating, wouldn't it?

The answer to a similar question suggests @overloading, but I guess that would imply somehow wrapping list.pop(), which would be even uglier in my eyes..

I'm using mypy 1.2.0

1

There are 1 best solutions below

0
frans On

Ok, after explaining my problem well enough I figured out I just had to type stack differently to be a list of NestedStringSequence (which it actually is, of course)..

from typing import Union

NestedStringSequence = list[Union[str, "NestedStringSequence"]]

element: NestedStringSequence = []
stack: list[NestedStringSequence] = [element]

stack.append([])
element = stack.pop()