Skip to content

Constraining a TypeVar to be not None seems impossible. #8881

Description

@tarcisioe

First of all, I'm using Mypy 0.770.

I'd like to annotate a function in the following way:

T = TypeVar('T')

class JSONSerialized(str, Generic[T]):
    """Strong type for the JSON serialized version of a type."""

@overload
def json_serialize(value: None) -> None:
    """Serialize value to its strong-typed JSON string type."""

@overload
def json_serialize(value: T) -> JSONSerialized[T]:
    """Serialize value to its strong-typed JSON string type."""

def json_serialize(value: Optional[T]) -> Optional[JSONSerialized[T]]:
    """Serialize value to its strong-typed JSON string type."""
    if value is None:
        return None

    return cast(JSONSerialized[T], json.dumps(to_json(value)))

The idea here is that I know that a string has been serialized from a given type (converted to a json-compatible type by the to_json function which is not depicted here.

The overloads don't work, however. I'd like them to inform mypy that this only returns None if None goes in, otherwise it doesn't. Unfortunately, since T is an unconstrained TypeVar, it also matches None, and mypy gives me the following error:

error: Overloaded function signatures 1 and 2 overlap with incompatible return types

Thus, I need a way to say "anything but None" (as a TypeVar in this case), but I can't seem to find any way to do so, so I believe this may end up being a feature request. I've seen similar behaviour being asked about in StackOverflow:

https://stackoverflow.com/questions/57854871/exclude-type-in-python-typing-annotation
https://stackoverflow.com/questions/47215682/what-type-represents-typing-any-except-none?noredirect=1&lq=1
https://stackoverflow.com/questions/58612057/how-to-make-a-generic-typevar-in-mypy-be-non-optional?noredirect=1&lq=1

Also, I'm not using any flags that change mypy's behaviour about None.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions