This question is in the context of Python 3.12 (so, making use of the latest type hinting features of the language) and the current version of mypy
for static type checking.
Consider the example function below, which would return either a complex object or a dict
, depending on what you ask the function to do. Is there a way yet in the language of specifying “I know which of the return values this function call is going to give me, when it can return multiple types”?:
def api_request(*args, as_json: bool = False, **kwargs) -> requests.Response | dict:
response = requests.request(*args, **kwargs)
if as_json is True:
return response.json()
return response
When I go to use this function elsewhere, this fails static type checking (I’m using mypy
):
def another_func():
response = api_request(as_json=True)
foo = response["foo"] # error: Value of type "Response | dict[Any, Any]" is not indexable [index]
This does not work:
response: dict = api_request(as_json=True) # error: Incompatible types in assignment (expression has type "Response | dict[Any, Any]", variable has type "dict[Any, Any]") [assignment]
This does, but feels to me to negate the whole point of using type hinting in the first place, because it’s not “any type”. It’s going to return a dict:
response: Any = api_request(as_json=True)
foo = response["foo"]
Commenting # type: ignore
on the line also works:
response = api_request(as_json=True)
foo = response["foo"] # type: ignore
But again, that feels like cheating / degrading the usefulness of the type-checking.
1