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
x
has typetype[t]
thenAnnotated[x, ...]
has typetype[t]
- Proposal: If
x
has 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.