-
I'd like to know if there's a way to type a class, where an init arg determines the signature of another method on the class. For example:
|
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 3 replies
-
Here's a solution that works with pyright. It doesn't work with mypy because of various bugs and limitations in how it handles from typing import Literal, overload
class X[T]:
@overload
def __new__(cls, grouped: Literal[True]) -> X[list[T]]:
...
@overload
def __new__(cls, grouped: Literal[False]) -> X[T]:
...
def __new__(cls, grouped: bool) -> X[list[T]] | X[T]:
...
def x(self, takes: T) -> None:
pass
x1 = X[int](True)
reveal_type(x1) # X[list[int]]
x2 = X[int](False)
reveal_type(x2) # X[int] |
Beta Was this translation helpful? Give feedback.
-
For an alternative that works in Mypy, it's doable by introducing another generic parameter: from typing import Literal, overload, TypeVar, Generic
T = TypeVar("T")
Grouped = TypeVar("Grouped", bound=bool)
class X(Generic[T, Grouped]):
def __init__(self, grouped: Grouped) -> None: pass
@overload
def x(self: X[T, Literal[True]], takes: list[T]) -> None:
pass
@overload
def x(self: X[T, Literal[False]], takes: T) -> None:
pass
def x(self, takes: T | list[T]) -> None:
pass
x1 = X[int, Literal[True]](True)
reveal_type(x1.x) # def (takes: builtins.list[builtins.int])
x2 = X[int, Literal[False]](False)
reveal_type(x2.x) # def (takes: builtins.int)
|
Beta Was this translation helpful? Give feedback.
Oh yes, actually it does, but the bound needs to be
Literal[True, False]