Skip to content

Can't have an alias that just targets a type variable #543

Closed

Description

@eric-wieser

Consider version 1 of my package, which defines

T = TypeVar('T', int, float)
MyType = Union[T, List[T]]

# in the user's code
U = TypeVar('U', int, float)
def myfunc(MyType[U], U): ...

In version 2, I decide to drop support for passing List[T]. However, this causes an error on the downstream type definitions

T = TypeVar('T', int, float)
MyType = Union[T]  # or Generic[T], or T - all fail

# downstream code doesn't change - I want the freedom to change `MyType` again in future
U = TypeVar('U', int, float)
def myfunc(MyType[U], U): ...  # fails due to missing __getitem__

Is there a way to write this? Does implementing TypeVar.__getitem__ seem reasonable? Or should we introduce Identity[T], which boxes a typevar into a generic?

Activity

  1. ilevkivskyi commented on Mar 14, 2018

    @ilevkivskyi
    Member

    This is the first time I see such request. TBH, I think it could be rather confusing for someone reading the code like this:

    T = TypeVar('T', int, float)
    U = TypeVar('U', int, float)
    MyType = T
    
    def func(arg: MyType[U]) -> U:
        ...

    So I am strong -1 on this.

  2. eric-wieser commented on Mar 14, 2018

    @eric-wieser
    Author

    So one related problem at the moment is the result of Union depends on it's arguments. This succeeds

    X = Union[T, int]
    X[str]
    

    Yet this fails

    X = Union[T]
    X[str]
    

    Contrast this with the equivalent C++ code, which just works:

    template<typename T>
    using X = union<T>;
    X<string> s;
    template<typename T>
    using X = union<T, int>;
    X<string> s;
  3. eric-wieser commented on Mar 14, 2018

    @eric-wieser
    Author

    Note that I give a real application in the referenced issue above. In python 3, we have

    T = TypeVar('T', *AnyStr.__constraints__)
    PathType = Union[T, PathLike[T]]
    
    # use PathType[str], PathType[bytes], PathType[AnyStr], etc

    But there is no way to specify this type on python 2, where PathLike doesn't exist, and the definition is just

    T = TypeVar('T', *AnyStr.__constraints__)
    PathType = ???[T]
    
    # PathType needs to be indexable just like in the py3 case
  4. ilevkivskyi commented on Jun 20, 2019

    @ilevkivskyi
    Member

    Hm, it looks like an experimental mypy_extensions.FlexibleAlias is exactly what can help in this case.

  5. changed the title [-]TypeVars should support indexing[/-] [+]Can't have an alias that just targets a type variable[/+] on Jun 20, 2019
  6. added
    topic: featureDiscussions about new features for Python's type annotations
    on Nov 4, 2021
  7. JelleZijlstra commented on May 22, 2023

    @JelleZijlstra
    Member

    PEP 695 addresses this. (Not on Python 2, but we don't care about that any more.)

    type MyType[T: (int, float)] = T
    
    # Or
    from typing_extensions import TypeAliasType, TypeVar
    
    T = TypeVar("T", int, float)
    MyType = TypeAliasType("MyType", T, type_params=(T,))
    
    def myfunc[U: (int, float)](a: MyType[U], b: U): ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    topic: featureDiscussions about new features for Python's type annotations

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions