It would be kind of cool / convenient if immutable containers, specifically tuple, NamedTuple and frozen dataclasses (with standard __init__), would automatically narrow field types based on their arguments. ty and pyright already do this for standard tuples; and I realized one can emulate the desired effect for NamedTuple / frozen dataclasses by introducing type variables:
from typing import NamedTuple
r: tuple[int, int, int | None] = (1,2,3)
reveal_type(r[2]) # ty, pyright: Literal[3], other: int | None
class Point(NamedTuple):
x: int
y: int
z: int | None
p = Point(1, 2, 3)
reveal_type(p.z) # all: int | None
class CleverPoint[Z: int | None](NamedTuple):
x: int
y: int
z: Z
q = CleverPoint(1, 2, 3)
reveal_type(q.z) # ty: Literal[3], other: int
Idea: type checkers could implicitly treat a NamedTuple
class NTuple(NamedTuple):
field1: type1
field2: type2
...
fieldN: typeN
as if it were:
class NTuple[T1: type1, T2: type2, ..., TN: typeN](NamedTuple):
field1: T1
field2: T2
...
fieldN: TN
I believe due to covariance this should generally be safe?!