[Python] How to type hint overload Callable and type differently?

Discussão em 'Python' iniciado por Stack, Maio 2, 2025.

  1. Stack

    Stack Membro Participativo

    How to type hint overload the return type of a Callable and type differently and safely? The problem I'm having is that the type doesn't support ParamSpec, so I can't use that to enforce args and kwargs, in the same way as as Callable.

    from collections.abc import Callable

    import typing_extensions as t

    P = t.ParamSpec("P")
    T_co = t.TypeVar("T_co", covariant=True)

    class ExpectCallable(t.Generic[P, T_co]): ...
    class ExpectType(ExpectCallable[P, T_co]): ...

    @t.overload
    def expect(
    v: type[T_co], /, *args: P.args, **kwargs: P.kwargs
    ) -> ExpectType[P, T_co]: ...
    @t.overload
    def expect(
    v: Callable[P, T_co], /, *args: P.args, **kwargs: P.kwargs
    ) -> ExpectCallable[P, T_co]: ...
    def expect(
    v: type[T_co] | Callable[P, T_co], /, *args: P.args, **kwargs: P.kwargs
    ) -> ExpectType[P, T_co] | ExpectCallable[P, T_co]:
    return ExpectType() if isinstance(v, type) else ExpectCallable()

    class A:
    def __init__(self, inp: str, /) -> None: ...

    def fn(inp: str, /) -> None: ...

    t.assert_type(expect(A), ExpectType[[], A]) # Shouldn't be allowed
    t.assert_type(expect(fn, "inp"), ExpectCallable[[str], None])


    As you can see that t.assert_type(expect(A), ExpectType[[], A]) passes with no errors, even though A is suppose to take in a str argument. I'm expecting expect(A) to require a str argument, similar to how expect(fn, "inp") requires the second parameter "inp".

    I understand that this is because A is a type, which doesn't have P to type the P.args and P.kwargs, but is there a way to achieve this in a type-safe way?

    Note that I haven't used *args and **kwargs in the example for simplicity, but they are meant to be used inside of the Expect classes.

    Continue reading...

Compartilhe esta Página