Typehints for Sized Iterable in Python : <p>I have a function that uses the <code>len</code> function on one of it's parameters and iterates over the parameter. Now I can choose whether to annotate the type with <code>Iterable</code> or with <code>Sized</code>, but both gives errors in <code>mypy</code>.</p>

<pre><code>from typing import Sized, Iterable


def foo(some_thing: Iterable):
    print(len(some_thing))
    for part in some_thing:
        print(part)
</code></pre>

<p>Gives</p>

<pre><code>error: Argument 1 to "len" has incompatible type "Iterable[Any]"; expected "Sized"
</code></pre>

<p>While</p>

<pre><code>def foo(some_thing: Sized):
...
</code></pre>

<p>Gives</p>

<pre><code>error: Iterable expected
error: "Sized" has no attribute "__iter__"
</code></pre>

<p>Since there is no <code>Intersection</code> as discussed in <a href="https://github.com/python/typing/issues/213" rel="noreferrer">this issue</a> I need to have some kind of mixed class.</p>

<pre><code>from abc import ABCMeta
from typing import Sized, Iterable


class SizedIterable(Sized, Iterable[str], metaclass=ABCMeta):
    pass


def foo(some_thing: SizedIterable):
    print(len(some_thing))
    for part in some_thing:
        print(part)


foo(['a', 'b', 'c'])
</code></pre>

<p>This gives an error when using <code>foo</code> with a <code>list</code>.</p>

<pre><code>error: Argument 1 to "foo" has incompatible type "List[str]"; expected "SizedIterable"
</code></pre>

<p>This is not too surprising since:</p>

<pre><code>&gt;&gt;&gt; SizedIterable.__subclasscheck__(list)
False
</code></pre>

<p>So I defined a <code>__subclasshook__</code> (see <a href="https://docs.python.org/3/library/abc.html#abc.ABCMeta.__subclasshook__" rel="noreferrer">docs</a>).</p>

<pre><code>class SizedIterable(Sized, Iterable[str], metaclass=ABCMeta):

    @classmethod
    def __subclasshook__(cls, subclass):
        return Sized.__subclasscheck__(subclass) and Iterable.__subclasscheck__(subclass)
</code></pre>

<p>Then the subclass check works:</p>

<pre><code>&gt;&gt;&gt; SizedIterable.__subclasscheck__(list)
True
</code></pre>

<p>But <code>mypy</code> still complains about my <code>list</code>.</p>

<pre><code>error: Argument 1 to "foo" has incompatible type "List[str]"; expected "SizedIterable"
</code></pre>

<p>How can I use type hints when using both the <code>len</code> function and iterate over my parameter? I think casting <code>foo(cast(SizedIterable, ['a', 'b', 'c']))</code> is not a good solution.</p>
