Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

mypy doesn't understand that the function returns a string

I have a function that returns a str or a specified fallback value (str or None). When giving a str fallback, the function is guaranteed to return a str. Running mypy on this however gives an error.

MWE:

from typing import Any


def f(x: str, fallback: str | None) -> str | None:
    if x.lower() == "yes":
        return "okay"
    return fallback


f("no", fallback="").lower()
f.py:10: error: Item "None" of "str | None" has no attribute "lower"  [union-attr]

How can I tell mypy that it’s safe to call lower() on the return value of the function?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

from typing import overload


@overload
def f(x: str, fallback: str) -> str:
    ...


@overload
def f(x: str, fallback: str | None = None) -> str | None:
    ...


def f(x: str, fallback: str | None = None) -> str | None:
    if x.lower() == "yes":
        return "okay"
    return fallback


f("no", fallback="").lower()
f("no").lower()

(type-)checks out:

  • f("no", fallback="").lower() is fine (since the fallback is passed in and a string)
  • f("no").lower() still says Item "None" of "str | None" has no attribute "lower"

Of course, if fallback is actually None, this will return a None, so you’ve broken the pinky-promise your types say.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading