I want to type hint get function so if I call get(int), returned value type will be inferred as int.
from typing import TYPE_CHECKING
Types = int | str
mapping: dict[type[Types], Types] = {
int: 6,
str: 'test',
}
def get[T](t: type[T]) -> T:
if TYPE_CHECKING:
reveal_type(t)
return mapping[t]
result = get(int)
if TYPE_CHECKING:
reveal_type(result)
print(result)
When I run mypy --strict I get:
type.py:12: note: Revealed type is "type[T`-1]"
type.py:13: error: Incompatible return value type (got "int | str", expected "T") [return-value]
type.py:13: error: Invalid index type "type[T]" for "dict[type[int] | type[str], int | str]"; expected type "type[int] | type[str]" [index]
type.py:18: note: Revealed type is "builtins.int"
The external interface of get works correctly already. But it’s internals currently cannot be typed correctly - you are going to need to use explicit casts/#type: ignore to silence the warnings.
You could also solve it by defining a polymorphic Mapping type. This way, you’ll only have to type ignore the assignment. Code sample in pyright playground
I think the easiest way to understand why this flags is this slight modification:
Types = int | str
mapping: dict[type[Types], Types] = {
int: 6,
str: 'test',
}
mapping = {
# switching keys around is still valid with existing
# annotation dict[type[Types], Types]
# and won't flag since the key value relationship is too simple,
# any key type could result in any of the value types
str: 6,
int: 'test',
}