Let's say I make a generic class whose objects only contain one value (of type T).
T = TypeVar('T')class Contains(Generic[T]): val: T def __init__(self, val: T): self.val = valNote that self.val can itself be a Contains object, so a recursive structure is possible. I want to define a function that will reduce such a structure to a single non-Contains object.
def flatten(x): while isinstance(x, Contains): x = x.val return xWhat should the type signature of 'flatten' be?
I tried to make a recursive Nested type
Nested = T | Contains['Nested[T]']but it confuses the type checker as T can also mean a Contains object.
def flatten(x: Nested[T]) -> T: while isinstance(x, Contains): reveal_type(x) # reveals Contains[Unknown] | Contains[Nested] x = x.val reveal_type(x) # reveals object* | Unknown return xAnother approach was to make a separate class
class Base(Generic[T]): self.val: T def __init__(self, val): self.val = valNested = Base[T] | Contains['Nested[T]']def flatten(x: Nested[T]) -> T: while isinstance(x, Contains): x = x.val return x.valThis works, but you have to wrap the argument in a Base object every time, which is cumbersome. Furthermore, Base has the same behaviour as Contains, it's the same thing written twice! I tried to use NewType instead, but it isn't subscriptable.
Is there any nice (or, at least not too ugly) way to do it?