-
Notifications
You must be signed in to change notification settings - Fork 287
[V2] Annotating custom constructor methods for generic types. #2026
Unanswered
randolf-scholz
asked this question in
Q&A
-
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])
Beta Was this translation helpful? Give feedback.
All reactions
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment