Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to write a negative python type annotation

This might sound unreasonable but right now I need to negate a type annotation. I mean something like this

an_int : Not[Iterable]
a_string: Iterable

This is because I wrote an overload for a function and mypy does not understand me. My function looks like this...

@overload
def iterable(o: Iterable) -> Literal[True] : ...

@overload
def iterable(o: Any) -> Literal[False] : ...


def iterable(o: Iterable|Any) -> Literal[True, False] :
    return isinstance(o, Iterable)

But mypy complains that overload 1 overlaps overload 2 and returns incompatible type.

A negating type annotation could easily solve this by using Not[Iterable] instead of Any in overload 2.

Does anyone know how to solve this problem?

like image 264
Dave Mcsavvy Avatar asked Oct 16 '25 04:10

Dave Mcsavvy


1 Answers

For your given example you can use TypeIs introduced in Python 3.13 (and back ported to typing_extensions).

from typing import Iterable, Any
from typing_extensions import TypeIs

def is_iterable(o: Any) -> TypeIs[Iterable]:
    """
    Check if an object is an iterable

    See https://stackoverflow.com/questions/1952464
    """
    try:
        iter(o)
    except TypeError:
        return False
    return True

a_list = [1,2]
if is_iterable(a_list):
    reveal_type(a_list)  # Revealed type is "builtins.list[builtins.int]"
    
a_int = 1
if not is_iterable(a_int):
    reveal_type(a_int)  # Revealed type is "builtins.int"

Check it out at MyPy Playground.

The original answer used TypeGuards to get the asked behaviour, which was dropped (PEP 724 but it was withdrawn, see reason) in favour of TypeIs (see discussion).

I am still interested in the negative type annotations, but for a use case that can't be solved with TypeGuard. But this refers to the long discussion about Intersections.

like image 166
Kound Avatar answered Oct 17 '25 17:10

Kound



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!