Type Error with tagged Unions (working code but mypy/pyright error)
functionally this code does what I expect it to (asserts go through) but there is a type error in the signature of Converter.structure, it accepts cl: type[T] and UnionType does not match that
from typing import Literal, Union
from dataclasses import dataclass
import cattrs
@dataclass
class Add:
t: Literal["ADD"]
v: int
@dataclass
class Sub:
t: Literal["SUB"]
v: int
Op = Union[Add, Sub]
Op2 = Add | Sub
assert cattrs.structure(dict(t="ADD", v=10), Op) == Add(t="ADD", v=10)
assert cattrs.structure(dict(t="SUB", v=5), Op2) == Sub(t="SUB", v=5)
if I change this https://github.com/python-attrs/cattrs/blob/main/src/cattrs/converters.py#L587 to
def structure(self, obj: UnstructuredValue, cl: type[T] | UnionType) -> T:
the type error goes away but I'm not sure if that is the right solution
There's not really a way to improve this on our own. We need PEP 747 to be accepted and implemented: https://peps.python.org/pep-0747/
The good news is that it's almost certainly going to be accepted, and the Mypy PR is in the final stages. I think pyright might already support it (when imported from a newer version of typing_extensions).
I don't want to add support until the PEP is formally accepted though. It's on our immediate radar though ;)
For now you'll have to use a # type: ignore unfortunately :/
that was quick, thanks for the link, great to know you are aware and tracking this issue :)
I just noticed that pyrefly can handle this, the type for x here is inferred as Add | Sub by the LSP
x = cattrs.structure(dict(t="ADD", v=10), Op)