Hi,
I'd like to write a PEP for a new typing construct: NotType which, would be equivalent to any type but x. There has been an issue open on the typing repo for quite some time about this (https://github.com/python/typing/issues/801). After the recent-ish proposal for an IntersectionType, this would be a nice-to-have feature as it would complete the set theory operations for typed Python. I'd also like to propose implementing type.__invert__ to make this work, so it has built-in syntax like intersection and union as this is the closest thing to a not operator.
Usecases:
Something that takes any non-empty string
```py
def fn(x: str & ~Literal[""]): ...
```
This also has nice integration with PEP 675 where the type of a Literal str is important. If you’d want to call this from any str you’d need a type guard.
```py
def guard(x: str) -> TypeGuard[str & ~Literal[“”]]:
return isinstance(x, str) and x != “” # or maybe bool(x) although this is probably much harder to implement
```
Something that takes any value but None
```py
def fn(x: ~Literal[None]): ...
```
Something that requires not an integer
```py
def not_an_int(x: Any) -> TypeGuard[~int]: ...
```
This also allows for narrowing in the negative case which is another requested feature (https://github.com/python/typing/issues/926)
```py
@overload
def is_none(value: None) -> Literal[True]: ...
@overload
def is_none(value: ~Literal[None]) -> Literal[False]: ...
def is_none(value: Any) -> bool: return value is None
def func(value: Optional[str]):
if is_none(value): reveal_type(value) # None
else: reveal_type(value) # str
```
Currently this isn’t the case
```py
def is_none(value: Any) -> TypeGuard[None]: return value is None
def func(value: Optional[str]):
if is_none(value): reveal_type(value) # None
else: reveal_type(value) # str | None
```
Overloading operators more correctly, more easily
```py
@overload
def __eq__(self, other: ~Self) -> Literal[False]: ...
@overload
def __eq__(self, other: Self) -> bool: ...
def __eq__(self, other: object) -> bool: return isinstance(other, self.__class__) and ...
```
Something fun
```py
reveal_type(~~str) # str
```
A few questions:
Can you see any issues here?
Do you have ideas for use cases I haven't thought of?
Does anybody want to be a co-author on this?
_______________________________________________
Typing-sig mailing list -- typing-sig@python.org
To unsubscribe send an email to typing-sig-leave@python.org
https://mail.python.org/mailman3/lists/typing-sig.python.org/
Member address: n.a.sobolev@gmail.com