Search code examples
pythonpython-typingmypy

MyPy - Incompatible types in assignment (expression has type None, variable has type X)


Does anyone have any idea why MyPy is complaining about this? It is extremely frustrating because it works if it's a ternary but not if in a standard if/else:

from typing import List, Optional, Union

def get_relevant_params() -> List[str]:
    return sorted(list(set(['1', '2', '3'])))

# also doesn't work with: ... -> Union[List[str], None]
def get_config(config_path: Optional[str] = None) -> Optional[List[str]]:
    
    # this doesn't work
    if config_path:
        read_cols = get_relevant_params()
    else:
        read_cols = None
        
    # # this works
    # read_cols = get_relevant_params() if config_path else None

    return read_cols

Here is an interactive MyPy playground with the example: https://mypy-play.net/?mypy=latest&python=3.8&gist=2c846e569ecbd5f8884367393a754adc


Solution

  • Change line 11 to read:

     read_cols: Optional[List[str]] = get_relevant_params()
    

    Your problem is that mypy identified the type of the variable read_cols automatically as a List[str] because that's the return type of get_relevant_params. Then when you try to assign None to it, it says "incompatible type". If you specify on variable creation that you want it to be optional, everything works.


    Maybe a cleaner solution is to avoid using a return variable.

        if config_path:
            return get_relevant_params()
        else:
            return None
    

    This way, there's never any confusion about the type of config_path.