Search code examples
pythongenericstypingpylancepyright

Expected no type arguments for class "Self"


I have a generic class, with a next method which returns an instance of itself parameterized to a difference type variable.

I can specify the next method's return type using " to reference the class itself:

DataIn = TypeVar('DataIn')
DataOut = TypeVar('DataOut')

@dataclass
class Msg(Generic[DataIn]):
    source: str
    data: DataIn


    def next(self, data: DataOut) -> "Msg[DataOut]":
        """
        Create a new message with the same source but different data
        """
        return Msg(source=self.source, data=data)

I would like to use the PEP 673 Self type to avoid the "':

    def next(self, data: DataOut) -> Self[DataOut]:

But that fails to type check in Pylance / Pyright:

    Expected no type arguments for class "Self"

The docs say: "Self can also be used in generic class methods", but don't show this specific use case.

Is it supported?


Solution

  • This is not supported, and not supported intentionally. In case of generic types Self refers (in regular methods - not classmethods) to some already parametrized instance.

    Quoting the docs (even the same section) that you linked:

    Note that we reject using Self with type arguments, such as Self[int]. This is because it creates ambiguity about the type of the self parameter and introduces unnecessary complexity:

    class Container(Generic[T]):
        def foo(
            self, other: Self[int], other2: Self,
        ) -> Self[str]:  # Rejected
            ...
    

    In such cases, we recommend using an explicit type for self:

    class Container(Generic[T]):
        def foo(
            self: Container[T],
            other: Container[int],
            other2: Container[T]
        ) -> Container[str]: ...