Replies: 3 comments 4 replies
-
There's currently no way in the type system to handle this. The typing spec is clear that a union is not assignable to If you're able to change the interface to this function, I recommend that you change it from accepting a UnionType to a tuple of type objects. A "union" is intended to describe a set-theoretical concept in type theory. It is not meant to describe a list of classes. So this Here's how I'd recommend coding this: from pathlib import Path
from typing import assert_type, overload
class Base:
pass
class A(Base):
pass
class B(Base):
pass
class C(Base):
pass
@overload
def load[T: Base](path: Path, type_: type[T]) -> T: ...
@overload
def load[T: Base](path: Path, type_: tuple[type[T], ...]) -> T: ...
def load[T](path, type_: type[T] | tuple[type[T], ...]) -> Base:
del path, type_
raise NotImplementedError
path = Path("moo")
x = load(path, A)
assert_type(x, A)
y = load(path, (A, B))
assert_type(y, A | B)
z = load(path, (A, B, C))
assert_type(z, A | B | C) |
Beta Was this translation helpful? Give feedback.
-
Thank you for the explanation; yes PEP 747 seems to be exactly what I was hoping existed.
How come? I intended that Interestingly, using the tuple approach it seems we can still pass in T = TypeVar("T", bound=Base)
@overload
def load[T: Base](path: Path, type_: type[T]) -> T: ...
@overload
def load[T: Base](path: Path, type_: tuple[type[T], ...]) -> T: ...
def load[T](path, type_: type[T] | tuple[type[T], ...]) -> Base:
del path, type_
raise NotImplementedError
path = Path("moo")
x = load(path, A)
typing.assert_type(x, A)
y = load(path, A | B)
typing.assert_type(y, A | B)
z = load(path, A | B | C)
typing.assert_type(z, A | B | C) does that make sense to you? |
Beta Was this translation helpful? Give feedback.
-
I guess the builtin
It's not just unions either - even just Personally I reverted to Pylance 2023.12.1 (not sure which Pyright version that corresponds to). That one doesn't raise the error, instead allowing |
Beta Was this translation helpful? Give feedback.
-
Testing with pyright 1.1.378
Consider the following minimal example. The real-world context is a function
load
that will deserialise an object somehow, and then ensure it is of some desired type or uniontype - so long as they're compatible with a bound.With the following approach, pyright flags an error where indicated:
However if I remove overload 2 then errors appear below:
where the ERROR is:
What's the correct way to handle this?
I'm also suspecting that there might be a bug in here, given that removing the second overload wasn't actually a no-op.
Beta Was this translation helpful? Give feedback.
All reactions