Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In python 3.9+, how to write a type alias for the builtin tuple type with ellipsis? (mypy bug?)

Short version

tuple[int, ...] is a valid type in python 3.9+ but mypy rejects a type alias for that. E.g. consider:

Thing = tuple[int, ...]

This results in "error: Unexpected '...'" (though python itself will load the module just fine).

Is this a bug in mypy?

What should/can I do? I thought maybe I could just use NewType instead but that fails in the same way.

Long version

Python 3.9 incorporates PEP 585, meaning we can use built-in types such as list, set and tuple as generics; as such the versions in typing are now deprecated (e.g. see docs for typing.Tuple).

mypy 0.800 introduced support for this, so now I can write the following and mypy will type-check it correctly:

def foo(a: tuple[int, str]):
    ...

Now, tuple (and typing.Tuple) of course have a special form for homogenously-typed tuples of unknown length: tuple[int, ...]; this works fine too:

def foo(a: tuple[int, ...]):
    ...

Handily, we can create aliases for types, so this works too:

from typing import Tuple

Thing = Tuple[int, ...]

def foo(a: Thing):
    ...

Unfortunately, the following (which puts together tuple, the ... form, and a type alias) does not work:

Thing = tuple[int, ...]

def foo(a: Thing):
    ...

Rather, this is rejected by mypy (v0.812) with the message "error: Unexpected '...'"

Python itself will load and run such a module just fine, however.

I haven't (yet) been able to find anything indicating that this shouldn't be possible. So:

  • Am I missing something? Is such a type alias in fact forbidden?

  • If not, is this a bug in mypy?

  • Are there any better ways for working around this than just using NewType instead of an alias?

    I thought using NewType would work around this (with some extra work) but it seems to fail in exactly the same way. So right now there seems to be no way to write these types and keep mypy happy.

like image 802
gimboland Avatar asked Sep 06 '25 00:09

gimboland


1 Answers

Aha, looks like it is indeed an open mypy bug.

So now the only question (until that's fixed/released) is how to work around it? Probably I have to bite the NewType bullet. :-/


Edit: hilariously, Thing = NewType('Thing', tuple[int, ...]) fails in exactly the same way.

like image 192
gimboland Avatar answered Sep 08 '25 14:09

gimboland