Thanks David. Here’s feedback on your latest draft. As Stefan and others have suggested, I think it’s worth having a discussion about why we wouldn't extend `Type[T]` to accommodate this use case. I can think of compelling arguments in favor and against doing so. At a minimum, a section should be added to the “Rejected Ideas” section explaining why this approach was not used. I think it’s important to formally explain what the type parameter for TypeForm means. The parameter describes the type of an _instance_ of the `TypeForm`. For example, `TypeForm[int | str]` describes a type that, when instantiated, is either an instance of `int` or an instance of `str`. This is important when considering signatures like `def foo(TypeForm[T]) -> T`. You state that the type _parameter_ for `TypeForm` is invariant, which is important to specify. However, I don’t think there is a need to say that a covariant or contravariant type variable used as a type _argument_ is illegal. That would be a really odd restriction that no other generic type imposes (including `Type`), and I don’t see any reason why it is necessary here. The variance of the _type parameter_ is what matters. I also don’t see any reason why to preclude the use of “bound” for a type argument. Why make a special case here when it’s not needed? There are even cases where it might be useful. I also don’t see a need to preclude the use of a class as a type argument (e.g. `TypeForm[int]`). This has a legitimate meaning, so why create an odd special case to preclude it? (As you can probably tell, I’m not a fan of special cases. There are too many of them in the Python type system already, IMO.) You specifically mention that `TypeForm` alone is equivalent to "`TypeForm[_T]` where `_T` is a freshly created type variable”. First, that’s an odd phrase, and I’m not sure how to interpret “freshly created type variable". Second, this is another situation where deviating from the normal rules is undesirable and unnecessary. By normal rules established in PEP 484, missing type arguments are assumed to be `Any`. That is, `TypeForm` should imply `TypeForm[Any]`. (Or in the case of Pyright, which distinguishes between explicit and implied `Any`, it means `TypeForm[Unknown]` and will be flagged as an error in strict mode.) I recommend deleting this sentence completely so as not imply that there is a special-case rule. The samples in the current draft use the “bare” form of `TypeForm` with no type arguments. I recommend against using (or encouraging the use of) the bare form. It will be considered an error in strict mode. Therefore, the samples should show an explicitly parameterized form: `TypeForm[Any]`. The `deunionize` sample contains a `cast` operation that masks an error. The `get_args` function returns a tuple, but the sample is casting it directly to a `list`, which will result in runtime errors if a caller tries to use it as a list. I recommend removing the cast entirely and either wrapping the results of `get_args(form)` in a `list()` constructor or (even better) changing the return type from `List[TypeForm]` to `Sequence[TypeForm[Any]]`. The `unionize` example contains the expression `Union[*components]` which is not legal syntax — at least not until PEP 637 is ratified and implemented. Is there another way to dynamically construct a `Union` object? I’m not aware of any way to do so in a way that a type checker would be able to reason about it. I don’t understand where `deunionize` and `unionize` operations (as shown in the examples) would be used. They provide no value for static type checking. Perhaps you have in mind use cases for dynamic (runtime) type checking? If the intent is to demonstrate a good static type checking use case for `TypeForm`, you might want to look for better examples. The section on “overloading” seems unnecessary to me. The fact that `TypeForm` works in an overload is implied by the previous sections of the spec. I guess it doesn’t hurt to say that it works with overloads, but it makes me wonder why overloads are specifically called out here. The section titled “Interactions with Type[C]” state, “it is not valid for a `TypeForm` and a `Type` to simultaneously constrain…”. I disagree with that statement. There are cases where such a constraint can be satisfied and cases where it cannot. For example, if someone were to call `bad_func(int, float)`, there is a valid solution (T => `float`) that satisfies all the constraints. In cases where the constraint cannot be met (e.g. `bad_func(Callable[…, Any], int)`), the constraint solver will detect that there is no valid solution and emit an error. So I don’t see a need to call this out as illegal. The normal rules of TypeVar constraint solving apply here, and no special case is needed. My recommendation is that you delete this entire section. -- Eric Traut Contributor to Pyright and Pylance Microsoft Corp.