That's not actually the key difference between the two forms of TypeVar. The version with bound= can substitute any subclass of the given bound, while the version with two or more positional type arguments can substitute only *exactly* those types.

Example:
```
from typing import TypeVar

class C(str): ...

AnyStr = TypeVar("AnyStr", str, bytes)
def f(arg: AnyStr) -> AnyStr: ...
reveal_type(f(C()))  # Line 7

T = TypeVar("T", bound=str)
def g(arg: T) -> T: ...
reveal_type(g(C()))  # Line 11
```
Output:
```
main.py:7: note: Revealed type is "builtins.str*"
main.py:11: note: Revealed type is "__main__.C*"
```

On Sat, Oct 30, 2021 at 5:29 PM Joren Hammudoglu <jhammudoglu@gmail.com> wrote:
This proposal got me thinking about TypeVar(..., A, B) vs TypeVar(..., bound=Union[A, B]). From what I can tell, the only difference is that the first one accepts an instance of class C(A, B), whereas the second one does not. This appears to be analogous to OR vs XOR. See https://mypy-play.net/?mypy=latest&python=3.10&gist=7f25463261d4775b37fcbdba04796e41

With this in mind, this syntax could unify typing constraints/restrictions and upper bounds by e.g. writing TypeVar('T', A, B) as T <= A | B , and TypeVar('T', bound=Union[A, B]) as T <= A ^ B.

However, the latter is a bit confusing, since Union[A, B] can be written with an A | B. But mypy does not allow it for TypeVar(..., bound=A | B), which makes sense if you consider that `class C(A | B)` and `class C(A, B)` are not the same (neither is `class C(Union[A, B])`, but that's besides the point).
_______________________________________________
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: guido@python.org


--
--Guido van Rossum (python.org/~guido)
Pronouns: he/him (why is my pronoun here?)