[ty] Distribute type[] over unions (#22115)
## Summary Closes https://github.com/astral-sh/ty/issues/2121.
This commit is contained in:
@@ -1179,6 +1179,34 @@ def _(
|
||||
reveal_type(subclass_of_p) # revealed: type[P]
|
||||
```
|
||||
|
||||
Using `type[]` with a union type alias distributes the `type[]` over the union elements:
|
||||
|
||||
```py
|
||||
from typing import Union
|
||||
|
||||
class C: ...
|
||||
class D: ...
|
||||
|
||||
UnionAlias1 = C | D
|
||||
UnionAlias2 = Union[C, D]
|
||||
|
||||
SubclassOfUnionAlias1 = type[UnionAlias1]
|
||||
SubclassOfUnionAlias2 = type[UnionAlias2]
|
||||
|
||||
reveal_type(SubclassOfUnionAlias1) # revealed: <special-form 'type[C | D]'>
|
||||
reveal_type(SubclassOfUnionAlias2) # revealed: <special-form 'type[C | D]'>
|
||||
|
||||
def _(
|
||||
subclass_of_union_alias1: SubclassOfUnionAlias1,
|
||||
subclass_of_union_alias2: SubclassOfUnionAlias2,
|
||||
):
|
||||
reveal_type(subclass_of_union_alias1) # revealed: type[C] | type[D]
|
||||
reveal_type(subclass_of_union_alias1()) # revealed: C | D
|
||||
|
||||
reveal_type(subclass_of_union_alias2) # revealed: type[C] | type[D]
|
||||
reveal_type(subclass_of_union_alias2()) # revealed: C | D
|
||||
```
|
||||
|
||||
Invalid uses result in diagnostics:
|
||||
|
||||
```py
|
||||
|
||||
@@ -71,6 +71,29 @@ reveal_type(constrained(str)) # revealed: str
|
||||
constrained(A)
|
||||
```
|
||||
|
||||
`type[T]` with a union upper bound `T: A | B` represents the metatype of a type variable `T` where
|
||||
`T` can be solved to any subtype of `A` or any subtype of `B`. It behaves similarly to a type
|
||||
variable that can be solved to any subclass of `A` or any subclass of `B`. Since all classes are
|
||||
instances of `type`, attributes on instances of `type` like `__name__` and `__qualname__` should
|
||||
still be accessible:
|
||||
|
||||
```py
|
||||
class Replace: ...
|
||||
class Multiply: ...
|
||||
|
||||
def union_bound[T: Replace | Multiply](x: type[T]) -> T:
|
||||
reveal_type(x) # revealed: type[T@union_bound]
|
||||
# All classes have __name__ and __qualname__ from type's metaclass
|
||||
reveal_type(x.__name__) # revealed: str
|
||||
reveal_type(x.__qualname__) # revealed: str
|
||||
reveal_type(x()) # revealed: T@union_bound
|
||||
|
||||
return x()
|
||||
|
||||
reveal_type(union_bound(Replace)) # revealed: Replace
|
||||
reveal_type(union_bound(Multiply)) # revealed: Multiply
|
||||
```
|
||||
|
||||
## Union
|
||||
|
||||
```py
|
||||
|
||||
Reference in New Issue
Block a user