Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[V2] Annotating custom constructor methods for generic types. #2026

Unanswered
randolf-scholz asked this question in Q&A
Discussion options

Follow up to #2025. Consider this simple example. Is there any way to annotate Array so that all the checks pass in both mypy and pyright?

from typing import Any, Self, assert_type
class Array[T = Any]:
 @classmethod
 def from_list(cls, x: list[T], /) -> Self:
 return cls()
assert_type(Array.from_list([]) , Array[Any])
assert_type(Array.from_list([1]) , Array[int])
assert_type(Array[int].from_list([]) , Array[int])
assert_type(Array[int].from_list([1]), Array[int])

I considered 5 different ways to implement it, including the use of metaclasses, but frustratingly, none of them make both mypy and pyright happy.

MWE in playground

Code sample in pyright playground

# fmt: off
from typing import Any, Self, assert_type
class Array1[T = Any]:
 @classmethod
 def from_list(cls, x: list[T], /) -> Self:
 return cls()
assert_type(Array1.from_list([]) , Array1[Any])
assert_type(Array1.from_list([1]) , Array1[int]) # Error in pyright
assert_type(Array1[int].from_list([]) , Array1[int])
assert_type(Array1[int].from_list([1]), Array1[int])
class Array2[T = Any]:
 @classmethod
 def from_list(cls: "type[Array2[T]]", x: list[T], /) -> "Array2[T]":
 return cls()
assert_type(Array2.from_list([]) , Array2[Any])
assert_type(Array2.from_list([1]) , Array2[int]) # Error in pyright
assert_type(Array2[int].from_list([]) , Array2[int])
assert_type(Array2[int].from_list([1]), Array2[int])
class Array3[T = Any]:
 @classmethod
 def from_list[X = Any](cls: "type[Array3[X]]", x: list[X], /) -> "Array3[X]":
 return cls()
assert_type(Array3.from_list([]) , Array3[Any])
assert_type(Array3.from_list([1]) , Array3[int]) # Error in pyright
assert_type(Array3[int].from_list([]) , Array3[int])
assert_type(Array3[int].from_list([1]), Array3[int])
class Array4Meta(type):
 def from_list[T = Any](cls, x: list[T], /) -> "Array4[T]":
 return cls()
class Array4[T](metaclass=Array4Meta): ...
assert_type(Array4.from_list([]) , Array4[Any])
assert_type(Array4.from_list([1]) , Array4[int])
assert_type(Array4[int].from_list([]) , Array4[int]) # Error in mypy and pyright
assert_type(Array4[int].from_list([1]), Array4[int])
class Array5Meta(type):
 def from_list[T = Any](cls: "type[Array5[T]]", x: list[T], /) -> "Array5[T]": # error in mypy and pyright
 return cls()
class Array5[T = Any](metaclass=Array5Meta): ...
assert_type(Array5.from_list([]) , Array5[Any]) # Error in mypy
assert_type(Array5.from_list([1]) , Array5[int]) # Error in mypy and pyright
assert_type(Array5[int].from_list([]) , Array5[int])
assert_type(Array5[int].from_list([1]), Array5[int])
You must be logged in to vote

Replies: 0 comments

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet
1 participant

AltStyle によって変換されたページ (->オリジナル) /