Skip to content

Instantly share code, notes, and snippets.

@MarcinKonowalczyk
Last active May 7, 2024 16:05
Show Gist options
  • Save MarcinKonowalczyk/afd1f7ec9e22686e6c3b347f94a1217e to your computer and use it in GitHub Desktop.
Save MarcinKonowalczyk/afd1f7ec9e22686e6c3b347f94a1217e to your computer and use it in GitHub Desktop.
generic namedtuple
from typing import TYPE_CHECKING, TypeVar, Generic, Tuple
from typing_extensions import reveal_type
T1 = TypeVar("T1")
T2 = TypeVar("T2")
if TYPE_CHECKING:
# This is how Group looks like to the type checker
class Group(Tuple[T1, T2], Generic[T1, T2]):
def __new__(cls, key: T1, group: T2) -> "Group[T1, T2]": ...
@property
def key(self) -> T1: ...
@property
def group(self) -> T2: ...
else:
# This is the actual implementation of Group, aka literally a tuple with two boltons
class Group(tuple):
def __new__(cls, key, group):
return tuple.__new__(cls, (key, group))
@property
def key(self):
return self[0]
@property
def group(self):
return self[1]
# Can unpack/index the Group because its literally a tuple at runtime
G1 = Group(1, "hello")
key1, grp1 = G1
key1 = G1[0]
grp1 = G1[1]
key1 = G1.key
grp1 = G1.group
# Types are ok
if TYPE_CHECKING:
reveal_type(key1) # Revealed type is "builtins.int"
reveal_type(grp1) # Revealed type is "builtins.str"
reveal_type(G1.key) # Revealed type is "builtins.int"
reveal_type(G1.group) # Revealed type is "builtins.str"
reveal_type(G1[0]) # Revealed type is "builtins.int"
reveal_type(G1[1]) # Revealed type is "builtins.str"
# And it *is* a generic
G2 = Group(False, 1.0)
key2, msg2 = G2
if TYPE_CHECKING:
reveal_type(key2) # Revealed type is "builtins.bool"
reveal_type(msg2) # Revealed type is "builtins.float"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment