You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
## Subtyping of protocols with `@classmethod` or `@staticmethod` members
2034
+
2035
+
The typing spec states that protocols may have `@classmethod` or `@staticmethod` method members.
2036
+
However, as of 2025/09/24, the spec does not elaborate on how these members should behave with
2037
+
regards to subtyping and assignability (nor are there any tests in the typing conformance suite).
2038
+
Ty's behaviour is therefore derived from first principles and the
2039
+
[mypy test suite](https://github.com/python/mypy/blob/354bea6352ee7a38b05e2f42c874e7d1f7bf557a/test-data/unit/check-protocols.test#L1231-L1263).
2040
+
2041
+
A protocol `P` with a `@classmethod` method member `x` can only be satisfied by a nominal type `N`
2042
+
if `N.x` is a callable object that evaluates to the same type whether it is accessed on inhabitants
2043
+
of `N` or inhabitants of `type[N]`, *and* the signature of `N.x` is equivalent to the signature of
2044
+
`P.x` after the descriptor protocol has been invoked on `P.x`:
2045
+
2046
+
```py
2047
+
from typing import Protocol
2048
+
from ty_extensions import static_assert, is_subtype_of, is_assignable_to, is_equivalent_to, is_disjoint_from
2049
+
2050
+
classPClassMethod(Protocol):
2051
+
@classmethod
2052
+
defx(cls, val: int) -> str: ...
2053
+
2054
+
classPStaticMethod(Protocol):
2055
+
@staticmethod
2056
+
defx(val: int) -> str: ...
2057
+
2058
+
classNNotCallable:
2059
+
x =None
2060
+
2061
+
classNInstanceMethod:
2062
+
defx(self, val: int) -> str:
2063
+
return"foo"
2064
+
2065
+
classNClassMethodGood:
2066
+
@classmethod
2067
+
defx(cls, val: int) -> str:
2068
+
return"foo"
2069
+
2070
+
classNClassMethodBad:
2071
+
@classmethod
2072
+
defx(cls, val: str) -> int:
2073
+
return42
2074
+
2075
+
classNStaticMethodGood:
2076
+
@staticmethod
2077
+
defx(val: int) -> str:
2078
+
return"foo"
2079
+
2080
+
classNStaticMethodBad:
2081
+
@staticmethod
2082
+
defx(cls, val: int) -> str:
2083
+
return"foo"
2084
+
2085
+
# `PClassMethod.x` and `PStaticMethod.x` evaluate to callable types with equivalent signatures
2086
+
# whether you access them on the protocol class or instances of the protocol.
0 commit comments