Search code examples
pythonmypy

How to avoid "Argument 1 to "join" of "str" has incompatible type "Callable[[], List[str]]"; expected "Iterable[str]"


A minimal example to reproduce this error could look like this

from enum import Enum
from typing import List


class Stuff(Enum):
    A = 'something'
    B = 'something_else'
    C = 'even_more'
    
    @classmethod
    @property
    def important_stuff(cls) -> List[str]:
        return [cls.A.value, cls.C.value]


print(f'{", ".join(Stuff.important_stuff)}')

That prints

something, even_more

as expected.

When I test this file with mypy I receive

error: Argument 1 to "join" of "str" has incompatible type "Callable[[], List[str]]"; expected "Iterable[str]"

What exactly causes this issue and how could I avoid it?


Solution

  • This looks to be a case where mypy needs some hard-coded logic to deal with the class method. mypy can handle the same classmethod-wrapped property on an ordinary class just fine.(Well, almost. You need an instance of Stuff, rather than the class itself, to invoke important_stuff.) The Enum subclass also appears to work as long as you access the property via an instance of Stuff rather than the class itself.

    $ cat tmp.py
    from enum import Enum
    from typing import List
    
    
    class Stuff:
        A = 'something'
        B = 'something_else'
        C = 'even_more'
    
        @classmethod
        @property
        def important_stuff(cls) -> List[str]:
            return [cls.A, cls.C]
    
    
    print(f'{", ".join(Stuff().important_stuff)}')
    
    $ mypy tmp.py
    Success: no issues found in 1 source file
    

    If that's the case, and until mypy is fixed, you can explicitly cast the value as an Iterable[str].

    from typing import cast, Iterable
    
    
    print(f'{", ".join(cast(Iterable[str], Stuff.important_stuff))}')