Skip to content

Type interference: ProtocolOf? #1944

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
kai3341 opened this issue Mar 7, 2025 · 2 comments
Open

Type interference: ProtocolOf? #1944

kai3341 opened this issue Mar 7, 2025 · 2 comments

Comments

@kai3341
Copy link

kai3341 commented Mar 7, 2025

I'm looking the way to interfere existing types explicitly, like typeof / keyof in Typescript

I have 2 use cases:

  • existing function definition -> Callable[...]
  • dataclass __init__ signature / protocol

I think it should look like:

from typing import ProtocolOf

def foo(a: int, b: float) -> float:
    return a * b

FooProtocol = ProtocolOf[foo]

Should be equal to:

class FooProtocol(Protocol):
    def __call__(a: int, b: float) -> float: ...

Or dataclasses:

from dataclasses import dataclass
from typing import ProtocolOf

@dataclass()
class Foo:
    a: int
    b: float

Here I'm not sure which way is better

# way 1:
FooProtocol = ProtocolOf[Foo]

Should be equal to:

class FooProtocol(Protocol):
    def __call__(a: int, b: float) -> Foo: ...
# way 2:
FooInitProtocol = ProtocolOf["Foo.__init__"]

Should be equal to:

class FooInitProtocol(Protocol):
    def __call__(a: int, b: float) -> None: ...

Callable / Protocol to ParamSpec / Returning to use in typing

I see typing.get_args but it doesn't looks suitable for typing. Also

from collections.abc import Callable
from typing import get_args

FooSignature = Callable[[int, float], float]
get_args(FooSignature)  # == [[int, float], float]

Instead of that it should be way to define FooParamSpec / FooReturning

Bonus

there are no way to convert TypedDict to ParamSpec.kwargs
UPD: is't bound to typing.Unpack

@kai3341
Copy link
Author

kai3341 commented Mar 7, 2025

Idea of ProtocolOf is quite raw. Maybe it have to require 2nd parameter keys as (keyof Target)[]. For example:

from dataclasses import dataclass
from typing import ProtocolOf

def foo(a: int, b: float) -> float:
    return a * b


@dataclass()
class Bar:
    a: int
    b: float


FooProtocol = ProtocolOf[foo, ["__call__"]]

# (a: int, b: float) => Bar
BarNewProtocol = ProtocolOf[Bar, ["__new__"]]

@Daraan
Copy link

Daraan commented Mar 12, 2025

(I am not a member here, so this is only my personal opinion)

This is lovely idea, I've written a similar idea recently, but as expected I was not the first to come up with an idea on this, for example you will find discussions and further links here for example:

However, typing_extensions is not the right place to discuss or introduce new ideas that still need consensus from the community. You fill find your idea better suited at the two places noted in the https://github.com/python/typing readme:

Improvements to the type system should be discussed on Python's Discourse, and are tracked in the issues in this repository.

Decide if you want to start a new discussion, or bring new input/support to the existing ones. And, hopefully we will get a concrete draft of a PEP on this to add this to the typing-specs. When more points are fledged out we can think of runtime implementations and how type-checkers have to support this.

@JelleZijlstra JelleZijlstra transferred this issue from python/typing_extensions Mar 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants