I’ve got a function deep_flatten
which takes a potentially nested list and flattens it. For instance: deep_flatten([1, [2, 3]])
returns [1, 2, 3]
.
I’m aware there are far better ways to go about it. This is just a toy example to experiment with Python typing and a few type checkers.
from collections.abc import Iterable
type NestedIter[T] = Iterable[T | NestedIter[T]]
def deep_flatten[T](input_iterable: NestedIter[T]) -> list[T]:
flattened: list[T] = []
for item in input_iterable:
if isinstance(item, Iterable):
flattened.extend(deep_flatten(item))
else:
flattened.append(item)
return flattened
if __name__ == "__main__":
res = deep_flatten([1, [2, 3]])
print(res)
The example above doesn’t raise any warnings or errors both with mypy --strict
and pyright
. However, if I check it with basedpyright
I get an error I’m struggling to make sense of:
/workspaces/flatten.py:10:30 - error: Argument of type "list[object]" cannot be assigned to parameter "iterable" of type "Iterable[T@deep_flatten]" in function "extend"
"list[object]" is not assignable to "Iterable[T@deep_flatten]"
Type parameter "_T_co@Iterable" is covariant, but "object" is not a subtype of "T@deep_flatten"
Type "object" is not assignable to type "T@deep_flatten" (reportArgumentType)
1 error, 0 warnings, 0 notes
The error propagates from flattened.extend(deep_flatten(item))
. The issue seems to be that the output of the recursive call, which is expected to be of type Iterable[T]
, is instead “evaluated” as list[object]
.
Is this an issue that can be solved? If so, I’d appreciate any suggestions on how to improve the typing in this example, an maybe a brief explanation as to why the output of the recursive call is not “evaluated” as I’d expect i.e. as Iterable[T]
.