TypeForm: Spelling for a type annotation object at runtime

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 type type[t] then Annotated[x, ...] has type type[t]
  • Proposal: If x has type TypeForm[t] then Annotated[x, ...] has type TypeForm[t]
  • Proposal: Otherwise Annotated[x, ...] has type object

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.