Is it possible to use an integer key with TypedDict (similar to dict?).
Trying a simple example:
from typing import TypedDict
class Moves(TypedDict):
0: int=1
1: int=2
Throws: SyntaxError: illegal target for annotation
It seems as though only Mapping[str, int]
is supported but I wanted to confirm. It wasn't specifically stated in the Pep docs.
The intent of TypedDict
is explicit in the PEP's abstract (emphasis added):
This PEP proposes a type constructor
typing.TypedDict
to support the use case where a dictionary object has a specific set of string keys, each with a value of a specific type.
and given the intended use cases are all annotatable in class syntax, implicitly applies only to dict
s keyed by strings that constitute valid identifiers (things you could use as attribute or keyword argument names), not even strings in general. So as intended, int
keys aren't a thing, this is just for enabling a class that uses dict
-like syntax to access the "attributes" rather than attribute access syntax.
While the alternative, backwards compatible syntax, allowed for compatibility with pre-3.6 Python, allows this (as well as allowing strings that aren't valid Python identifiers), e.g.:
Moves = TypedDict('Moves', {0: int, 1: int})
you could only construct it with dict
literals (e.g. Moves({0: 123, 1: 456})
) because the cleaner keyword syntax like Moves(0=123, 1=456)
doesn't work. And even though that technically works at runtime (it's all just dict
s under the hood after all), the actual type-checkers that validate your type correctness may not support it (because the intent and documented use exclusively handles strings that constitute valid identifiers).
Point is, don't do this. For the simple case you're describing here (consecutive integer integer "keys" starting from zero, where each position has independent meaning, where they may or may not differ by type), you really just want a tuple
anyway:
Moves = typing.Tuple[int, int] # Could be [int, str] if index 1 should be a string
would be used for annotations the same way, and your actual point of use in the code would just be normal tuple
syntax (return 1, 2
).
If you really want to be able to use the name Moves
when creating instances, on 3.9+ you could use PEP 585 to do (no import required):
Moves = tuple[int, int]
allowing you to write:
return Moves((1, 2))
when you want to make an "instance" of it. No runtime checking is involved (it's roughly equivalent to running tuple((1, 2))
at runtime), but static type-checkers should understand the intent.