-
I'm writing some code like this: from typing import Callable, Self, reveal_type
class A[T]:
def do_nothing(self, b: T) -> Self:
...
def replace[Tx](self, b: Tx) -> "A[Tx]":
...
a = A[Callable[[], None]]() # here is an error but ignore it for now
@a.do_nothing
def a() -> None: # redeclaration error, have to ignore it since it is intentional
...
reveal_type(a) # Type of "a" is "A[() -> None]"
@a.replace
def a(foo: int) -> None: # error because of this
...
reveal_type(a) # Type of "a" is "A[(foo: int) -> None]" # type changed intentionally The similar pattern appears on |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
The I recommend against using this pattern in your own classes if you want them to work well with static typing. If you choose to use this pattern, you'll need to handle the ramifications of the redeclarations. One workaround is to avoid using the same symbol name for different type declarations, like this: from typing import Callable, Self
class A[T]:
def do_nothing(self, b: T) -> Self: ...
def replace[Tx](self, b: Tx) -> "A[Tx]": ...
a1 = A[Callable[[], None]]()
@a1.do_nothing
def a2() -> None: ...
@a2.replace
def a(foo: int) -> None: ... |
Beta Was this translation helpful? Give feedback.
The
property
class requires extensive special-casing within type checkers and is exempted from redeclaration checks.I recommend against using this pattern in your own classes if you want them to work well with static typing. If you choose to use this pattern, you'll need to handle the ramifications of the redeclarations.
One workaround is to avoid using the same symbol name for different type declarations, like this: