I'm trying add type annotations to an ElementList
object that inherits from list
and can contain either Element
objects or other ElementGroup
objects.
When I run the following code through mypy:
from typing import Self
class Element:
pass
class ElementList(list[Element | Self]):
pass
elements = ElementList(
[
Element(),
Element(),
ElementList(
[
Element(),
Element(),
]
),
]
)
I get the following error:
element.py:8: error: Self type is only allowed in annotations within class definition [misc]
Found 1 error in 1 file (checked 1 source file)
What's the recommended way to add typing annotations to this so that mypy doesn't throw an error?
Your sample list argument to the ElementList
constructor contains not just Element
s and ElementList
s but also actual list
s, so a workaround of class ElementList(list["Element | ElementList"]): ...
would not have worked, as @dROOOze pointed out in the comment, because list
is not a subtype of ElementList
.
You can work around this limitation with a type alias, which can refer to itself without creating a subtype:
class Element:
pass
type ElementListType[T] = Element | T | list[ElementListType[T]]
class ElementList(list[ElementListType["ElementList"]]):
pass
elements = ElementList(
[
Element(),
Element(),
[
Element(),
ElementList(
[
Element(),
Element(),
]
)
],
]
)
Demo with mypy here
Demo with pyright here