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
Ideally, this snippet would work. It enables making multiple types that share the same implementation but don't subclass each other (like newtype in other languages). If you comment out the other.quack() call and the bound="Foo[DerivedT]") then it will typecheck -- the issue is specifically with being able to express a typevar bound indicating the typevar has a base class that uses that typevar as a generic parameter.
#!/usr/bin/env python
from __future__ import annotations
from typing import Generic, TypeVar
DerivedT = TypeVar("DerivedT", bound="Foo[DerivedT]")
class Foo(Generic[DerivedT]):
def quack(self) -> None:
print("quack!")
def quack_together(self, other: DerivedT) -> None:
self.quack()
other.quack()
class Bar(Foo[Bar]): pass
x = Bar()
y = Bar()
x.quack_together(y)
$ python -m mypy --strict /tmp/self_test.py
self_test.py:6: error: Type variable "self_test.DerivedT" is unbound [valid-type]
self_test.py:6: note: (Hint: Use "Generic[DerivedT]" or "Protocol[DerivedT]" base class to bind "DerivedT" inside a class)
self_test.py:6: note: (Hint: Use "DerivedT" in function signature to bind "DerivedT" inside a function)
Found 1 error in 1 file (checked 1 source file)
Mypy version used: mypy 1.10.0 (compiled: yes)
Mypy configuration options from mypy.ini (and other config files): N/A
Python version used: 3.12
The text was updated successfully, but these errors were encountered:
The closest related issue is #11063 where it looks like the author separately ran into this issue because they use Base[Any] as the bound instead of Base[T].
An imperfect workaround for anyone who stumbles on this later:
Make the bound Base[Any].
Change all methods from operating on DerivedT to operating on Base[DerivedT] (this is mostly okay since we assume the only class that satisfies this is DerivedT)
If you need to construct an instance of the derived, do type(self)(args)
Anywhere you return a type(self)(args) instead of returning DerivedT or Base[DerivedT] return Self -- this helps callers if you have any extra methods on DerivedT that they expect to be able to call on the object returned from your method
This gets you most of the way there without having to introduce a ton of casts and isinstance asserts in the internal code or for callers. But it would still be clearer if bound=Base[DerivedT] worked :)
Bug Report
Ideally, this snippet would work. It enables making multiple types that share the same implementation but don't subclass each other (like
newtype
in other languages). If you comment out theother.quack()
call and thebound="Foo[DerivedT]"
) then it will typecheck -- the issue is specifically with being able to express a typevar bound indicating the typevar has a base class that uses that typevar as a generic parameter.mypy.ini
(and other config files): N/AThe text was updated successfully, but these errors were encountered: