Skip to content

Cannot return concrete type within isinstance block of generic function #8354

Closed
@PeterJCLaw

Description

@PeterJCLaw

I'm not sure if this is a bug or a known limitation. I think this is different to the other similar generics vs isinstance issues, but please do point me at another if this is a duplicate.

Given some function:

from typing import TypeVar

T = TypeVar('T')

def foo(val: T) -> T:
    if isinstance(val, str):
        return "abc"
    return val

I would hope that mypy can tell that, within the isinstance block, T can only be str (since that's what val is) and thus returning something which is explicitly str is fine.

Unfortunately this case seems to error:

foo.py:5: error: Incompatible return value type (got "str", expected "T")

I realise this construct looks a bit odd in the cut-down above -- my actual use-case involves walking nested list and dictionary structures to modify values, but ends up with what I believe is the same error. Just to give a sense of that a slightly larger but still very cut-down version would be:

from typing import Any, List, TypeVar, Union

T = TypeVar('T', bound=Union[str, List[Any], int])

def do_expansion(value: T) -> T:
    if isinstance(value, str):
        return value.upper()  # just using .upper() as an example
    elif isinstance(value, list):
        return [do_expansion(x) for x in value]
    else:
        return value

I realise I could use overloads to achieve a similar effect for consumers of the function, however I would also like to be able to type the implementation and get checking there.

In case it's useful, I'm using mypy version 0.761 (latest at the time of writing) on Python 3.5.2.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions