Neoteroi / rodi

Implementation of dependency injection for Python 3
MIT License
179 stars 17 forks source link

Improve `resolve()` typing #59

Open sobolevn opened 4 months ago

sobolevn commented 4 months ago

Using Union[Type[T], str] is problematic, because when str is passed, mypy infers T to be Never. Instead, you should use an overload with two cases, so inference would be correct:

from typing import Any, TypeVar, Union, Type, overload

T = TypeVar('T')

class My:
    def resolve(  # type: ignore[empty-body]
        self,
        obj_type: Union[Type[T], str],
    ) -> T:
        ...   # in reallity we would return something here

reveal_type(My().resolve(int))
# N: Revealed type is "builtins.int"
reveal_type(My().resolve('a'))
# N: Revealed type is "Never"

class Other:
    @overload
    def resolve(self, obj_type: Type[T]) -> T: ...
    @overload
    def resolve(self, obj_type: str) -> Any: ...
    def resolve(self, obj_type: Any) -> Any: ...

reveal_type(Other().resolve(int))
# N: Revealed type is "builtins.int"
reveal_type(Other().resolve('a'))
# N: Revealed type is "Any"

Link: https://mypy-play.net/?mypy=latest&python=3.12&gist=97dd0c638b48950199067e8290e5595e&flags=strict

This way users can actually use Any type, while Never type cannot be used for literally anything.