Combining mypy Union and nested TypedDict causes mypy errror: incompatible return value

Viewed 893

I would like to combine TypedDict with with Union. So that a function is able to return either A or B. Mypy is able to correctly detect a TypedDict return type directly. But when a TypedDict is nested in an Union it doesn't work.

from typing_extensions import TypedDict
from typing import Union


class A(TypedDict):
    a: str


class B(TypedDict):
    b: str


def works() -> A:
    return {'a': 'value'}
    # Works as expected


def problem() -> Union[A, B]:
    return {'a': 'value'}
    # mypy_error: Incompatible return value type (got "Dict[str, str]", expected "Union[A, B]")
    # Reports an error while it should be valid


def workaround() -> Union[A, B]:
    x: A = {'a': 'value'}

    return x
    # This works again but is not very elegant

A possible workaround would be to assign to temporary returned type hinted variable (see workaround()). Is there a more elegant way of doing this?

Note: Python 3.7

1 Answers

A quote from PEP 589:

An explicit [TypedDict] type annotation is generally needed, as otherwise an ordinary dictionary type could be assumed by a type checker, for backwards compatibility. When a type checker can infer that a constructed dictionary object should be a TypedDict, an explicit annotation can be omitted.

So there's nothing wrong with defining the type explicitly in your code. Another possibility is to "instantiate" A directly:

def problem() -> Union[A, B]:
    return A(a='value')

Although this is of course only a syntactic sugar and will be replaced with dict at runtime.

Related