typeshed icon indicating copy to clipboard operation
typeshed copied to clipboard

Empty Collection Handling with `next`

Open max-muoto opened this issue 1 year ago • 0 comments

There are some issues when using next when providing an empty collection as a default, let's take this example:

from collections.abc import Iterable


def foo(iter: Iterable[list[int]]) -> None:
    next((item for item in iter if len(item) > 5), [])

This leads to errors in Pyright, as [] is treated as list[unknown]. Pyright Playground.

Here are the current next overloads:

@overload
def next(i: SupportsNext[_T], /) -> _T: ...
@overload
def next(i: SupportsNext[_T], default: _VT, /) -> _T | _VT: ...

I would propose changing the second one to:

def next(i: SupportsNext[_T], default: _VT | _T, /) -> _T | _VT: ...

This would fix the above issue, as in the case an empty list or othe rcollection Pyright could just infer the type as _T, while not disrupting other cases in which the types differ.

With this change in Pyright:

from typing import reveal_type

def foo(iter: Iterable[list[int]]) -> None:
    result = next((item for item in iter if len(item) > 5), [])
    reveal_type(result) # Revealed type is `list[int]`.

max-muoto avatar May 30 '24 16:05 max-muoto