Quantcast
Channel: Active questions tagged python - Stack Overflow
Viewing all articles
Browse latest Browse all 23131

Mypy type narrowing with recursive generic types

$
0
0

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 = val

Note 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 x

What 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 x

Another 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.val

This 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?


Viewing all articles
Browse latest Browse all 23131

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>