I am looking for a way to type hint a function that returns a tuple containing a success flag and, in the case of success, None, or, in the case of failure, an Exception instance. Declaring the function as returning tuple[bool, Union[Exception, None]] obviously doesn't work -- there is no way for the type checker to know whether the second element of the tuple is an Exception or None, so when I write, e.g., raise result[1], pyright complains that None does not inherit from BaseException. I have tried overloading the return value, i.e. @overload def validate(value: MyClass) -> tuple[Literal[True], None]: ... @overload def validate(value: MyClass) -> tuple[Literal[False], Exception]: ... def validate(value: MyClass) -> tuple[bool, Union[Exception, None]]: try: value.validate() except Exception as e: return False, e return True, None def do_something(value: MyClass): success, error = validate(value) if not success: raise error value.do_something() But because the arguments are identical in both overloads, pyright seems to think I am always calling the first overload, and that the return value is always Literal[True], None. A simpler example also demonstrates the issue: from typing import Literal, reveal_type type T = tuple[Literal[True], None] | tuple[Literal[False], Exception] def test(t: T): a, b = t reveal_type(a) # bool reveal_type(b) # Exception | None if not a: reveal_type(a) # Literal[False] reveal_type(b) # Exception | None raise b # <-- Invalid exception class or object; "None" does not derive from BaseException (PylancereportGeneralTypeIssues) This seems like a fairly common use-case, but I can't find a way to do it. This also doesn't work with mypy. Continue reading...