@erictraut thanks for taking the time to detail several questions RE the “value expression + type expression mixing” issue.
TypeForm[T] values that already fit in type[T]
Conceptually TypeForm[T]
and type[T]
behave very similarly in my mind. Calling out some specific examples:
-
As a value expression,
Movie
(referring to a typed dict) has typetype[Movie]
according to pyright. mypy says something similar:reveal_type(Movie) # pyright: "type[Movie]" # mypy: "def (*, title: builtins.str) -> TypedDict('typeddict.Movie', {'title': builtins.str})" def identity_type(t: type[T]) -> type[T]: return t reveal_type(identity_type(Movie)) # pyright: "type[Movie]" # mypy: "type[TypedDict('typeddict.Movie', {'title': builtins.str})]"
TypeForm[T] values that do not fit in type[T]
For those type expressions that, when parsed as a value expression, do not currently have type type[t]
(for some t
), I’d like them to ideally have type TypeForm[t]
instead:
-
Stringified type expressions
I think the user would have to explicitly mark string literals that are intended to be treated as TypeForms with the
TypeForm(...)
syntax you recently proposed.- Proposal: As a value expression,
TypeForm("bool")
(with quotes) has a type ofTypeForm[bool]
. - Proposal: As a value expression,
"bool"
(with quotes) continues to have typeLiteral["bool"]
.
- Proposal: As a value expression,
-
Unions
Given each operand of an
x | y
expression,x
andy
, is itself a value expression with a type:- Proposal: If
x
has typetype[t1]
orTypeForm[t1]
, andy
has typetype[t2]
orTypeForm[t2]
, thenx | y
has typeTypeForm[t1 | t2]
. Otherwisex | y
has typeUnionType
.
- Proposal: If
-
Bare Forms
Currently pyright and mypy disagree on the type of various special forms, with mypy mostly saying they are type
object
:reveal_type(Any) # mypy: "builtins.object" # pyright: "Any" reveal_type(Never) # mypy: "typing._SpecialForm" # pyright: "Never" reveal_type(Literal["words"]) # mypy: "builtins.object" # pyright: "type[Literal['words']]" reveal_type(Callable[[], None]) # mypy: "builtins.object" # pyright: "type[() -> None]"
- Proposal: As a value expression,
Any
has a typeTypeForm[Any]
. - Proposal: As a value expression,
Never
has a typeTypeForm[Never]
. - etc
- Proposal: As a value expression,
-
None
Users writing
None
are almost certainly are intending to spell theNone
value rather than theNone
type. So in the rare cases that theNone
type is intended, users would need to use theTypeForm(None)
syntax to spell it:- Proposal: As a value expression,
TypeForm(None)
has a type ofTypeForm[None]
. - Proposal: As a value expression,
None
continues to have a type ofNone
.
- Proposal: As a value expression,
TypeForm(T)
as an explicit way to spell an object T
with type TypeForm[T]
I think it could be useful to have an explicit spelling of TypeForm(T)
to mean “T when treated as a value”. I think this explicit spelling may actually be necessary to disambiguate a few cases (mentioned above).
At runtime the callable TypeForm()
would just return its single argument unchanged. Type checkers could recognize TypeForm(t)
and specially parse the t
inside as a type expression, and give it type TypeForm[t]
.
Fin
Thoughts @erictraut ?