mypy: How to declare the return type of a method returning self in a generic class?

jakun

This answer does not seem to work for generics. Mypy complains about "error: Missing type parameters for generic type A" when checking the following code. I have tried using 'A[T]' for the TypeVar but then mypy says "error: Type variable T is unbound." I have also tried using AnyA[T] as return type of get but that produces two error messages, the already known "error: Missing type parameters for generic type A" and the new error message "Type variable AnyA used with arguments".

How do I specify the return type of get correctly?

import typing

T = typing.TypeVar('T')
AnyA = typing.TypeVar('AnyA', bound='A')

class A(typing.Generic[T]):

    def __init__(self, val: T) -> None:
        self.val = val

    def get(self: AnyA) -> AnyA:
        return self

class B(A[T]):
    def is_int(self) -> bool:
        return isinstance(self.val, int)


if __name__ == '__main__':
    b = B(42)
    print(b.get().is_int())
hoefling

I know of three ways of typing here:

Declaring an inner self-type

This approach is described in mypy docs, see Precise typing of alternative constructors.

class A(typing.Generic[T]):
    _Self = typing.TypeVar('_Self', bound='A[T]')

    def __init__(self, val: T) -> None:
        self.val = val

    def get(self: _Self) -> _Self:
        return self

Note however, that this is mypy-specific stuff and may not work with other checkers. E.g. pyre doesn't support inner self-types yet.

Using _typeshed.Self

This saves the boilerplate of declaring custom types, but requires a somewhat obscure import from typeshed which will fail at runtime. It thus must be wrapped by typing.TYPE_CHECKING:

from typing import Any, TYPE_CHECKING

if TYPE_CHECKING:
    from _typeshed import Self
else:
    Self = Any

class A(typing.Generic[T]):
    def __init__(self, val: T) -> None:
        self.val = val

    def get(self: Self) -> Self:
        return self

_typeshed.Self was created to be used in custom stubs in the first place, but is suitable for inline typing as well.

Python 3.11 and upwards: typing.Self

A recently introduced PEP 673 adds Self to stdlib, so starting from Python 3.11 one will be able to use that:

from typing import Self

class A(typing.Generic[T]):
    def __init__(self, val: T) -> None:
        self.val = val

    def get(self: Self) -> Self:
        return self

This is not supported by mypy yet as of now though, but e.g. by pyright from version 1.1.184.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

How to declare parameter type according to class method return type?

Declare Generic method in a "normal" class and its return

How to return instance of concrete class from method with generic return type

Delegate for generic class and method with generic return type

How to return class type of a generic class with generic?

Java method returning type of generic type of generic used at class

How to return the Class of a generic type

How to create generic method to return generic type

Return class of generic type in default interface method

Method return type using enclosed Generic class?

Method receiving and returning generic type - how to do it?

Mypy: How to take a Type as function argument and invoke a class method on that type

Generic method returning generic type

How to declare a list so it contains a generic class no matter the generic type?

How to declare an inter-type method with return type of every object's class?

TypeScript declare method return type is instance type of class or subclass

How to declare generic class generic?

How to declare a set type of an enum type within a generic class

Python typing, mypy infer return type based on class method return type

How can I return self in a class method?

Overriding a method, mypy throws an "incompatible with super type" error when changing return type to child class type

How to return a generic type from a nested class using a method in the main class

In Swift, how does a method return a generic type?

How to do a covariant generic return type in a method?

How to make method return class wrapping generic

Generic type parameters C# - How to generic class return type

Method with generic return type

Generic type method return

Generic method return generic type