I want to convey to the type checker that a particular attribute contains 64 elements of type Piece|None
. How can I write that ?
I tried tuple[((Piece|None),)*64]
but PyLance doesn’t recognize it. tuple[(Piece|None), 64]
doesn’t either. tuple[piece|None]
apparently does the same without checking the length, which is what I settled with, hoping writing a 710 character long line is not the only available alternative.
I believe there is no way typing tuples of a specific length. Type checkers usually don’t track tuple length, e.g. Unpacking tuples of variable length · Issue #1178 · python/mypy (github.com).
Actually, mine does. I have fun2 which takes two parameters (required), and when I write this :
def fun1(a : tuple[int]):
fun2(*a)
then Pylance sends a warning about it, which shuts up when I write tuple[int, int]
instead. So, it does appear that for it tuple[int]
doesn’t mean “a tuple containing ints”, but “a singleton tuple containing one int”.
Maybe this differs among type checkers ?
I believe the syntax a tuple containing ints is tuple[int, ...]
. It doesn’t check length though.
I recently wrote up some new docs on annotating tuples here, which may be useful: typing — Support for type hints — Python 3.11.4 documentation
Thanks ! That helps. I suppose there’s no dedicated way of declaring a tuple of length 64 of homogenous type then ? None of my tries using tuple multiplication worked.
Well, strictly speaking there is, you can type it using:
from typing import TypeAlias
_P: TypeAlias = Piece | None
Tuple64: TypeAlias = tuple[_P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P]
def func(a: Tuple64) -> None: pass
…That’s the best that the typing system currently has to offer, though
Yeah, that’s not much simpler than my former solution, I guess I’ll stick with tuple[Piece|None, ...]
then too bad for length checking
Upvote Feature Request: Type hint for Fixed Length Homogeneous Sequences · Issue #786 · python/typing · GitHub (or even better, write a PEP to add it to Python’s type system ) if you’re interested in improving Python typing in this area
Do type checkers accept this?
Tuple64: TypeAlias = tuple[*(Piece | None,) * 64]
No – not static type checkers (mypy, pyre, pyright, pytype, etc.), anyway. You might be use it with it if you’re using a runtime type checker like typeguard or beartype, though.
In general, it would open up a large can of worms if we started expecting static type checkers to dynamically evaluate arbitrary expressions in type annotations. It’s not something we ever ask of them at the moment.
Yeah, that’s what I was afraid of. Oh well.
Remember that static type checkers never actually run your code; they’re just making inferences from the AST of your code. They don’t have an arbitrary understanding of arbitrary Python code that you might want to put inside a type annotation; any new kind of expression in a type annotation has to have special-case logic manually added to a type checker in order for the type checker to understand it. This is [one of the reasons] why the kinds of expressions allowed in type annotations are pretty limited, and why dynamically computing type annotations is generally problematic.