CarliJoy / intersection_examples

Python Typing Intersection examples
MIT License
33 stars 2 forks source link

The PEP should use & exclusively #12

Closed NeilGirdhar closed 1 year ago

NeilGirdhar commented 1 year ago

The PEP is inconsistent and uses Intersection sometimes. It would be better to exclusively use the & notation, and mention the Intersection as existing solely in typing_extensions for backwards compatibility.

randolf-scholz commented 1 year ago

Intersection only existing in typing_extensions would be confusing, since Union does exist in typing. Also, for certain special applications, one might need to have the type available. For example, imagine someone writing a script for automatically adding annotations to code. How are they supposed to type-hint a function that detects Intersections and returns the annotation, if the Intersection-type is not available?

NeilGirdhar commented 1 year ago

. How are they supposed to type-hint a function that detects Intersections and returns the annotation, if the Intersection-type is not available?

Okay, good point.

Still, we should avoid Intersection completely I think. There's no good reason to encourage anyone to use that.

randolf-scholz commented 1 year ago

I just want to mention one more example here, which requires Union and Intersection, which is when the number of things intersected is variable. This can happen when TypeVarTuple are involved, and it kind of implies that a speccing of empty unions and empty intersections is necessary. (See https://github.com/python/typing/issues/1362)

from typing import TypeVarTuple, Union

items = TypeVarTuple("items")
protocols = TypeVarTuple("protocols")   
# technically we want TypeVarTuple("protocols", bound=type[Protocol])
# but bounds are not supported yet for TypeVarTuple.

def pick_random_element(tup: tuple[*items]) -> Union[*items]: ...
    """Return random element form a tuple."""
    # if tuple is empty, raises an exception ⟺ return `Never`.

def merge_protocols(protos: tuple[*protocols]) -> Intersection[*Protocols]: ...
    """Creates the intersection of pairwise disjoint protocol classes."""
    # if intersection is empty, returns a protocol that matches with any class.

EMPTY_TUPLE = ()
pick_random_element(EMPTY_TUPLE)  # should reveal as `Union[()]` ≅ `Never`.
merge_protocols(EMPTY_TUPLE)  # should reveal as `Intersection[()]` ≅ `object`!?

Note that bounds are (not yet) supperted by TypeVarTuple, so the latter cannot be hinted properly right now.

NeilGirdhar commented 1 year ago

@randolf-scholz Okay, I thought about it, and I see what you're getting at.