PEP 747: TypeExpr: Type Hint for a Type Expression

Type expression terminology

The most straightforward spelling for the concept, type or Type, is unfortunately already in use for spelling class objects which do not encompass all types.

Early on I proposed widening the existing definition of type to match any type and not just class objects but got pushback from various mypy folks, mostly on backward-compatibility grounds.

Code that manipulates TypeExpr objects at runtime is typically actually manipulating the syntactic elements of the expression, looking at the origin / args of the expression, etc. Therefore I think it makes sense to still call the concept an “expression”.

The name “type form” specifically is problematic which is why a new name was chosen.

TypeExpr without brackets

Final is allowed to infer its argument:

my_const: Final = 5
# Is a Final[int]

It seems to me that allowing similar inference for TypeExpr would provide good ergonomics:

typx: TypeExpr = int | str
# Is a TypeExpr[int | str]

It sounds like your main objection is that inferring the parameter would be difficult to implement. If so, I think the main place it seems to be helpful to infer the parameter is in a direct variable assignment like in the example above. Perhaps in that specific case it wouldn’t be too hard to infer?

FWIW, Any is explicitly allowed by the current wording.

Rules for unions

Interesting. Sounds like I’ll need to tweak the rules so that UnionType continues to be inferred for the cases that you mention. And then state explicitly that UnionType is treated as a subtype of TypeExpr.

Rules for Annotation Expressions

Ah. I originally added this section based on feedback from you. But I can easily delete the section. I’m fine leaving the type of annotation expressions undefined, as they currently are today.

Subtyping Rules

If I were to delete this rule then there would be no rules for how to treat TypeExpr[Any] vs. type[Any] because the “subtyping” relation (as PEP 483 defines it) does not apply to Any. Only “is-consistent-with” (recently rebranded to “assignability”) applies to Any. So I still think I need this rule.

I can rephrase to avoid the term “plain type” though.

Literal[] TypeExprs

I’ll rephrase to use this justification.