Aye. I can enumerate in the next PEP draft rules for parsing each kind of type expression in a value expression context.
It would be useful to define that incomplete type expressions (like Union, Optional, Annotated - with no type arguments) should have type object. That would guarantee that you’d get a reasonable error message if you spelled something that is close to valid. Currently you see errors that look like:
def identity_type(t: type[T]) -> type[T]:
return t
identity_type(Literal)
# pyright: Argument of type "type[Literal]" cannot be assigned to parameter "t" of type "type[T@identity_type]"
# mypy: Argument 1 to "identity_type" has incompatible type "<typing special form>"
Ideally annotation expressions which aren’t type expressions (like Required[...], Final, etc) should also be defined to have type object. I don’t think there’d be too many additional cases to write out so I think it would be OK to enumerate them.
There’s a corner case for Annotated[...] because it sometimes is a type expression and sometimes is an annotation expression:
- Proposal: If
xhas typetype[t]thenAnnotated[x, ...]has typetype[t] - Proposal: If
xhas typeTypeForm[t]thenAnnotated[x, ...]has typeTypeForm[t] - Proposal: Otherwise
Annotated[x, ...]has typeobject
Ah yes. I think I meant here to write something like “Otherwise x | y has the type implied by the binary-or bitwise-or of x and y”. For example the type of 5 | 2 would be int.
I agree that I don’t think there’s a case where you’d end up with UnionType here if the type and TypeForm cases were already checked.
Agreed. I’ll add a mention to the next PEP draft.