Type hints can be any expression
The official Python grammar doesn't specify a narrowed expression grammar for type annotations. For example, looking at the grammar for a function argument:
arg = (identifier arg, expr? annotation, string? type_comment)
It actually allows any expression to be used for a type annotation. For example, the following code is valid Python syntax:
def foo(t: type) -> type:
if t is str:
return int
else:
return str
def bar(t: foo(str)) -> foo(int):
return "wat"
if __name__ == "__main__":
print(foo(str))
print(foo(type(None)))
print(bar(1))
Running that yields the following output:
<class 'int'>
<class 'str'>
wat
Attempting to type check the function with MyPy will result in an error:
-> % mypy test.py
test.py:8: error: Invalid type comment or annotation [valid-type]
test.py:8: note: Suggestion: use foo[...] instead of foo(...)
Found 1 error in 1 file (checked 1 source file)
Type checking with pyright
will result in a similar error.
PEP-484, which specifies type hints in Python, advises that they should be simple expressions but there is nothing in the language itself that stops you from doing this or more absurd examples such as:
def bar(t: (int if foo(str)[-1] + 7 % 2 == 0 else type(None)) = None) -> foo(int):
...