microsoft / pyright

Static Type Checker for Python
Other
13.04k stars 1.39k forks source link

Union of legit types is also a legit type #8390

Closed sassanh closed 1 month ago

sassanh commented 1 month ago

Describe the bug In this code the last line causes a reportArgumentType pyright error.

Code or Screenshots

class OriginalType: ...

class SubclassOne(OriginalType): ...

class SubclassTwo(OriginalType): ...

UnionType = SubclassOne | SubclassTwo

def some_function(_: type[OriginalType]): ...

some_function(OriginalType)
some_function(SubclassOne)
some_function(SubclassTwo)
some_function(UnionType) # <-- Pyright reports `UnionType` is not acceptable here
erictraut commented 1 month ago

This behavior is correct, so I don't consider this a bug. Pyright's behavior here is in conformance with the typing spec.

The type of UnionType when used in a value expression is types.UnionType.

U = SubclassOne | SubclassTwo
reveal_type(U)  # UnionType

When it's used in a type expression, it acts as a type alias for the type SubclassOne | SubclassTwo.

In your case, you're using it in a value expression (an argument for a function call), and its type is not compatible with type[OriginalType].

For comparison, all othe other major type checkers including mypy also generate an error here. This behavior is conformant with the typing spec. For details, refer to this section.

You may be interested in draft PEP 747 that provides a way to annotate "type forms".