Hi friends. Thanks for the discussion! As it may be helpful, here is a motivating use case for nested scope aliases: backward compatible name changes to types. For example, in a library we might have ``` class A: class B_new: pass B_old: TypeAlias = B_new def get_B() -> B_new: # impl ``` Here, we renamed the inner class from `B_old` to `B_new` but would like to keep some backward compatibility for some time between old name and new name for customers of this library who may have preexisting code: ``` b: B_old = A().get_B() ```
I think there are several defensible positions to take, but let me propose the following: * Both implied type aliases (introduced in PEP 484) and explicit type aliases (introduced in PEP 613) are allowed within module, class and function scopes. * Type aliases that use bound type variables (those defined within a class or function scope) are forbidden and should generate an error. This would require us to 1) revise PEP 484 for clarity, 2) revise PEP 613 to loosen the requirements. I don't think it would require any changes to mypy. It would require a small bug fix in pyright, but I plan to make that change regardless. I haven't tested the behavior of the other type checkers (pyre, pytest, PyCharm), so I'm not sure what changes would be required in those cases. Thoughts?
This makes sense to me. There is one further place of ambiguity that should be clarified in the PEP ``` X = int class A: Y = int ``` Should X and Y be inferred as a type alias on `int` or `Type[int]`? Mypy has a whole section of documentation about this ambiguity - https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-a... - though it does not describe the explicit `TypeAlias` syntax or the behavior heuristic inside nested scope. Currently in mypy, `X` is inferred as a type alias and `A.Y` is inferred as a class variable of type `Type[int]`. Mypy chooses to treat `A.Y` as a variable (intentionally) as a heuristic inside nested scope. See this comment from a couple years back https://mail.python.org/archives/list/typing-sig@python.org/message/QNJEVUIH... In pyright, both `X` and `A.Y` are inferred as type aliases. I think without an explicit type of either `Y: TypeAlias = int` or `Y: Type[int] = int`, we should have a consistent experience specified by PEP613 on what `Y = int` should look like. Some options - Inferred as a TypeAlias - Inferred as a class variable - Specify that the type checker should raise an error here - asking the user to be explicit IMO - inferring as TypeAlias will be more useful in more cases. It also has the benefit of having consistent behavior across scopes (least surprise), and more compatible with PEP 484's initial introduction of type aliases, meaning more compatible with existing code.