Inconsistencies between `Type` and `type`

The behavior here is indeed confusing and inconsistent. This would be a good area to address by the Typing Council as a spec clarification once the Council is constituted.

I think there are two things that type/type[Any] could mean:

  • An object that only allows operations that are valid on all types (analogous to object). With this interpretation, we should allow operations like t.__name__ that work on all types, but we should not allow accessing attributes like t.x that don’t exist on all types. Both mypy and pyright allow spelling this as type[object] or Type[object] (and so do pyanalyze and pytype, but pyre treats type and Type differently).
  • An object that is a type, but allows any operation that might be valid on some type (analogous to Any). This is how mypy treats type[Any]: for a variable t of type type[Any], t.__name__ is str (because that attribute is present for any type), but t.x is Any. I’ll call this “type[Any]”, though not all type checkers treat type[Any] this way.

For completeness, I’ll note that pyre, pytype, and pyanalyze all produce no errors on your code sample, though they differ in exactly what types they infer.

The text of PEP 484 seems to say that type/Type/Type[Any] should all be equivalent and mean type[object] as I defined it above. However, that’s not what any type checker has actually implemented.

Now, how should type checkers behave?

First, type and Type should mean exactly the same thing. That’s how all other pre-PEP 585 aliases behave, and it’s confusing for type to be different. That means both mypy and pyright have a bug in this area.

Next, type[Any] probably should have the behavior I outlined above for it (an object that is a type but also allows any operation that might be valid on some type). That’s how most type checkers except pyright treat it. I’m not sure how useful this behavior is, though, and it does create a weird entry in the type system, an “Any for types”.

Last, should plain type be equivalent to type[Any] or type[object]? The former is more consistent with the rest of the type system, and with the current text of PEP 484.

So I would say that your code sample should produce no errors: all of these annotations are equivalent to type[Any] and should allow arbitrary attributes.

4 Likes