
Thanks for writing this proposal. I do think this is a valuable addition to the type system, and I’m generally supportive of the idea as long as it remains simple and we can avoid feature creep. Here are some thoughts… *Default ordering* I'm not convinced that we need to enforce ordering here. In effect, every type variable already has an implicit default value of `Any`, so it is unnecessary for type checkers or the runtime to detect cases where a TypeVar with no explicit default comes after a TypeVar with an explicit default. This is just added complexity that limits flexibility of the feature. I recommend deleting this entire section. I noticed that there's a section under "rejected alternatives" that tries to justify the default ordering constraint. I don't buy the justification here because, as I mentioned above, there's really no such thing as a TypeVar without a default. There's just "explicit defaults" and "implicit defaults". That's a very different situation from parameters in a call signature. *Constrained TypeVars* You talk about the interaction between bound TypeVars and default, but you don’t specify the interaction between constrained TypeVars and default. For constrained TypeVars, I think the default needs to be the same type as one of the constraints. It would be an error if it were a subtype. ```python T1 = TypeVar("T1", int, str, default=int) # OK T2 = TypeVar("T2", int, str, default=float) # Error ``` *Use of generics in default* The PEP doesn't explicitly disallow the use of generics in the default type. I think this is implied, but it would be better if it was explicitly called out as invalid. ```python T1 = TypeVar("T1", default=T) # Error T2 = TypeVar("T2", default=list[T]) # Error ``` *Function defaults* I don't understand why a function parameter annotated with a TypeVar with a default must have a default argument value associated with it. Why are the two concepts (a default type argument type and a default argument value for a parameter) related? If this is required, what about more complicated parameter type annotations that involve a TypeVar with a default type argument, such as `T | None` or `List[T]`? What about cases where the TypeVar appears for multiple input parameters? ```python DefaultIntT = TypeVar("DefaultIntT", default=int) def bar(a: DefaultInt = 0, b: DefaultInt = 0) -> DefaultInt: ... bar(3.14) ``` Unless there's a strong justification for tying these two concepts together, I would recommend deleting this entire section and removing this constraint. I think it unnecessarily complicates the design and takes us down a rabbit hole of additional concerns that would need to be discussed and addressed in the PEP. Let's avoid that if possible. *TypeVarTuple* Can more complex forms of unpacked tuples be used in the default value? I think the answer is probably yes, but it would be good to include an example. ```python Ts = TypeVarTuple("Ts", default=(int, *tuple[float, ...], str)) ``` *TypeVarTuple "subscription"* This subsection could use some additional text to explain the problem and the proposed solution. I'm trying to infer the intent from the code sample. I think the intent here is to avoid an ambiguity when a TypeVarTuple is used with a "suffix" that includes a TypeVar with a default. There are two ways to avoid that ambiguity. One is to disallow the use of a TypeVar with a default in a suffix. The other way is to simply document how it will be interpreted in that case. Your sample here seems to imply that it works in a prefix position by requiring that a type argument be provided explicitly. Maybe that's the same rule that should apply for suffixes. I don't have a strong opinion on this one, but I prefer consistency between prefixes and suffixes unless there's a good reason for them to be inconsistent. *ParamSpec Defaults* Is `...` a legal default for ParamSpec? It probably should be, since that's the implicit default. I presume that Concatenate cannot be used in a ParamSpec default. It might be good to call that out explicitly. *Missing type argument detection and reporting* Pyright has a diagnostic rule called reportMissingTypeArgument that emits a diagnostic when a generic class is used in an annotation without providing the expected type arguments. I don't know if mypy, pyre or pytype have a similar feature. The introduction of default type argument values will necessarily affect that logic. I don't know if this is worth mentioning in the PEP. It's something I'll need to consider if/when I implement this feature in pyright. *Specifying a default of Any* I wonder if the PEP should express an opinion about an explicit default of `Any`. The implicit default is already `Any`, but there's an important distinction between the two, at least for pyright which distinguishes between explicit `Any` and implicit `Any`, which it refers to as `Unknown`. I would like to encourage people (especially library authors) _not_ to use an explicit `Any` default, because that will potentially mask type errors. *Alternative syntax* Shantanu suggested an alternative syntax that brings the default closer to the code. I'd recommend against doing that in this PEP. I think we all recognize that the current syntax for TypeVars in Python is problematic and a fix is needed, but let's not do it piecemeal. That's bound to create problems. I like that this proposal fits in nicely with the existing TypeVar infrastructure and syntax. If we deviate from that, getting the PEP accepted will be more difficult, and we're likely to complicate our efforts in the future to improve the overall syntax for TypeVars. *Specifying defaults of one TypeVar in terms of another TypeVar* @syastrov asked whether the default type argument for one TypeVar could depend on the type argument provided for a different TypeVar. I understand the use case, but I'd strongly push back on this requirement. Many programming languages have support for default type arguments, but I've never seen one that supports defaults that depend on other type argument values — and there's a good reason for this. It would greatly complicate the design. Perhaps there are other ways to solve the problem with django stubs, but this doesn't strike me as a viable solution. -Eric -- Eric Traut Contributor to Pyright & Pylance Microsoft