From my recent efforts to clean up incorrect TypeVar usages in the Google
codebase, I've discovered that users already find many creative ways to
misunderstand and misuse TypeVar. Echoing Sebastian's earlier point, I
think it would be a bad idea to reuse TypeVar to also mean AnyOf, since
that would contradict the current state of a TypeVar being meaningful only
when it appears multiple times in a definition and likely cause even more
confusion.
Re: Richard's observation about pytype and unsafe unions: yes, we had them
for practical reasons, and yes, we've been making things stricter ever
since because of reports of missed bugs and surprising behavior.
Best,
Rebecca
On Tue, Sep 22, 2020 at 12:30 AM Eric Traut
I see some value in adding an "AnyOf" construct for return types, but a type checker won't be able to do much with this information because (as others have pointed out), it would be unsafe to make many assumptions about the type. The most significant benefit is that language servers could provide completion suggestions — something developers would definitely appreciate.
That said, I don't think we need to introduce a new "AnyOf" type. As Zac pointed out, there's already a construct in the Python type system that has the desired properties of "AnyOf". Rather than invent a new construct, I'd prefer to leverage the constrained TypeVar.
Adding support for a new "AnyOf" type would likely be a lot of work in Pyright, but leveraging constrained TypeVars would be nearly free. In fact, it mostly works already, and I was able to implement completion suggestions and type narrowing with just a few additional lines of code. I'm guessing this it would be easy for most existing type checkers to add this support.
Mypy might require some small changes because it appears to use the first type in a constrained TypeVar rather than retaining the full list of constraints. I'm assuming that's not the intended behavior and is just a bug.
Zac said:
I don't believe you can currently have a return typevar without an argument typevar...
I don't see anything in PEP 484 that states that a TypeVar used within a return type annotation must also appear in a parameter type annotation. Mypy doesn't appear to enforce this either, nor does the "stubtest" CI test for typeshed. There are legitimate uses for this. Here's an example:
```python def my_decorator(timeout: float) -> Callable[[_T], _T]: ... ```
Building on Zac's example, here's how this could work:
```python from typing import TypeVar from ipaddress import IPv4Address, IPv6Address
IPAddress = TypeVar("IPAddress", IPv4Address, IPv6Address)
def ip_address(s: str) -> IPAddress: if len(s.split('.')) == 4: return IPv4Address(s) else: return IPv6Address(s)
a = ip_address("1.2.3.4") reveal_type(a)
if isinstance(a, IPv4Address): print("IPv4!") reveal_type(a) else: print("IPv6!") reveal_type(a) ```
Pyright's output is: ``` Found 1 source file 15:13 - info: Type of "a" is "IPAddress" 19:17 - info: Type of "a" is "IPv4Address" 22:17 - info: Type of "a" is "IPv6Address" 0 errors, 0 warnings, 3 infos ```
Mypy's output is: ``` test.py:9: error: Incompatible return value type (got "IPv4Address", expected "IPv6Address") test.py:11: error: Incompatible return value type (got "IPv6Address", expected "IPv4Address") test.py:15: note: Revealed type is 'ipaddress.IPv4Address*' test.py:19: note: Revealed type is 'ipaddress.IPv4Address*' Found 2 errors in 1 file (checked 1 source file) ``` (This looks like a bug. Perhaps someone from the mypy team could speak to how difficult a fix would be.)
(@Zac — You might be interested in the fact that I recently added support for recursive types in Pyright. https://devblogs.microsoft.com/python/pylance-introduces-five-new-features-t... )
-Eric
-- Eric Traut Microsoft _______________________________________________ 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: rechen@google.com