Replies: 1 comment 3 replies
-
Also there is another way I found that does not use that hack, but I'm waiting a clarification from It has two assumptions:
With those we can: from __future__ import annotations
from dataclasses import dataclass
from typing import Any, Generic, Literal, NoReturn, Type, TypeVar, overload
from typing_extensions import LiteralString
K = TypeVar("K", bound=LiteralString)
V = TypeVar("V")
@dataclass(frozen=True)
class Getter(Generic[K]):
key: K
@overload
def __getitem__(self, record: Type[tuple[K, V]]) -> Type[V]: ...
@overload
def __getitem__(self, record: Type[tuple[Any, Any]]) -> NoReturn: ...
def __getitem__(self, record: Any) -> Any: ...
Got = Getter("foo")[
tuple[Literal["hi"], int] | tuple[Literal["bye"], str] | tuple[Literal["foo"], bool]
]
# (type alias) Got: Type[bool] By collapsing all non-matching values to |
Beta Was this translation helpful? Give feedback.
3 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
TL;DR:
&
) in pyright, by being careful about bounding orderTried reddit and discord, also don't think it's on mypy scope, maybe on typing if I'd be asking it as a feature but idk, pyright seems to be rolling a superset of it's own and I just wanna know if it's intended effect here
AFAIK there is no official way to make extensible typed record or TS-like
intersection
(&
operator) in mypy/pyright, meaning, you can't define a function like:In a way that would keep the type info on the resulting dict.
Still there is an approach that I'm almost sure is legal: instead of keeping track of the dict, we keep track of key-value pair type, so we can do element type union to achieve collection type intersection (as in oop/subtying intersection):
Now it works as expected:
Hopefully nothing hacky so far. The problem is retrieving a typed value from key, the closest solution I found was doing pattern matching:
Again, hopefully nothing hacky so far. But yeah, doesn't seem to be possible to do it in a generic
K = TypeVar('K', bound=LiteralString)
key variable.But then I noticed, by carefully ordering typevar binding order, it actually is possible, although not in a instance bound method but in a curried function (or in a generic callable class):
And the line
Record[tuple[K, V] | AnyPair]
is what I wanna know if is hackySo, is it? I'm matching against a union, in a way that does make sense to me, especially if I think about the
M
inclass Record[M]
as covariant, I mean, never went looking for it but I assumeA | Any <: A | B | C | D | E
for mypy/pyright/typescript, the only doubt is if the resolving ofA | Any
collapses toAny
before that type-level pattern matching is done.Also just to be sure, the manipulation of typevar bounding order, is it ok to count on it in general? Or is it just a unintended side effect of pyright's type inference? That feature I've been using quite a lot in other more 'normal' code, so I was counting on it being ok.
More complete and careful implementation at the gist
Beta Was this translation helpful? Give feedback.
All reactions