Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow applying generic types to TypeVarTuple #17861

Closed
eltoder opened this issue Oct 1, 2024 · 3 comments
Closed

Allow applying generic types to TypeVarTuple #17861

eltoder opened this issue Oct 1, 2024 · 3 comments
Labels

Comments

@eltoder
Copy link

eltoder commented Oct 1, 2024

Feature

If Ts is a TypeVarTuple, using it in a generic type Foo will be equivalent to applying Foo to every component of the tuple. I.e. Foo[Ts] will be logically equivalent to (Foo[T1], Foo[T2], ...) where T1, T2 are the components of the tuple. Foo[Ts] itself will be treated like a TypeVarTuple, except that its components are not plain type variables, but an application of Foo.

Pitch

This will help giving better types to zip-like functions. Currently, these functions are typed using @overload, for example:

class map(Iterator[_S]):
    @overload
    def __new__(cls, func: Callable[[_T1], _S], iter1: Iterable[_T1], /) -> Self: ...
    @overload
    def __new__(cls, func: Callable[[_T1, _T2], _S], iter1: Iterable[_T1], iter2: Iterable[_T2], /) -> Self: ...
    @overload
    def __new__(
        cls, func: Callable[[_T1, _T2, _T3], _S], iter1: Iterable[_T1], iter2: Iterable[_T2], iter3: Iterable[_T3], /
    ) -> Self: ...
    ...

class zip(Iterator[_T_co]):
    @overload
    def __new__(cls, iter1: Iterable[_T1], /, *, strict: bool = ...) -> zip[tuple[_T1]]: ...
    @overload
    def __new__(cls, iter1: Iterable[_T1], iter2: Iterable[_T2], /, *, strict: bool = ...) -> zip[tuple[_T1, _T2]]: ...
    @overload
    def __new__(
        cls, iter1: Iterable[_T1], iter2: Iterable[_T2], iter3: Iterable[_T3], /, *, strict: bool = ...
    ) -> zip[tuple[_T1, _T2, _T3]]: ...
    ...

This is very verbose and error-prone, and also introduces an arbitrary limit for the number of arguments. (typeshed stubs support up to 6 arguments for map and zip and up to 10 for itertools.product.)

With the proposed feature these can be typed simply as:

class map(Iterator[_S]):
    def __new__(cls, func: Callable[[*_Ts], _S], *iters: *Iterable[_Ts]) -> Self: ...

class zip(Iterator[_T_co]):
    def __new__(cls, *iters: *Iterable[_Ts], *, strict: bool = ...) -> zip[tuple[*Ts]]: ...
@eltoder eltoder added the feature label Oct 1, 2024
@erictraut
Copy link

A feature like this would likely require a PEP and an update to the Python typing spec. The Python typing forum would be a good place to discuss the idea.

A related idea was proposed here if you're interested in commenting (or collaborating) on that proposal.

@eltoder
Copy link
Author

eltoder commented Oct 1, 2024

@erictraut Thank you. Indeed this is a very similar proposal, and I agree with your comments in that thread.

@jorenham
Copy link

See also python/typing#1216

@eltoder eltoder closed this as completed Oct 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants