Pyre hasnít supported non-global aliases in the past, but Iím OK with consistent behavior for aliases nested in classes as with global aliases (ie., an explicit `TypeAlias` annotation is an option if clarity is needed, or youíre using quoted annotations, etc., but backwards-compatible inference following the rules Eric laid out still works).

I agree that we should throw type errors if any bound type variable is referenced in a type alias.


My only remaining question is Ė why support type aliases inside function scopes? I donít think there is meaningful value-add, and having to deal with a different type hierarchy based on scoping sounds like unnecessary complexity to me. Similarly with type aliases defined as instance variables, or anything beyond toplevel globals or class variables, which are essentially qualified globals.


From: Shantanu Jain <>
Date: Thursday, November 4, 2021 at 1:20 AM
To: Eric Traut <>
Cc: None via Typing-sig <>
Subject: [Typing-sig] Re: PEP 613 and type aliases in nested scope

As is often the case, I agree with Eric and find myself with little to add beyond a +1 to the position Eric suggested :-)


mypy's current heuristics are similar to pyright's, except that simple assignments in nested scope are considered variables, not aliases (as Nipunn mentioned, relevant code). With PEP 613, I personally don't feel particularly strongly about that additional heuristic... Although maybe there is an appeal to be made to Chesterton's Fence, given that Ivan and Jukka went out of their way to include that heuristic, even though the pre-PEP 613 world left users no recourse to get mypy to treat those as type aliases. I'll check how much code gets flagged by mypy_primer if I remove it.


Both of you are right that consistency is better for users. I did a bad job of expressing the core of the point I wanted to make, which was something like: if the intent of the user is clear (as the case of `def f(): X: TypeAlias = int` feels to me), I tend to default to the position that type checkers should follow that intent and it shouldn't be prohibited without a discussion like the one we're having now :-)


If we find we're in agreement / this thread dies off, I think I have the following action items:

1) Make PRs to clarify PEP 484 and loosen requirements in PEP 613

2) See if changing mypy's heuristic regarding nested scopes to match pyright causes regressions for mypy users

3) Update the mypy documentation page Nipunn linked



On Wed, 3 Nov 2021 at 11:56, Eric Traut <> wrote:

FWIW, pyright currently uses the following heuristics to distinguish an implicit (inferred) type alias definitions from a regular variable assignment.

A type alias is inferred if all of the following conditions apply:
1. There is no type annotation provided
2. There is only one assignment to the symbol
3. The expression on the RHS of the assignment does not contain any syntactic form that would be considered illegal for a type annotation (call expressions, lambdas, comprehensions, etc.)
4. The type evaluation of the RHS evaluates to an instantiable type or a union of instantiable types

The current heuristics don't require that the symbol is in the global (module-level) scope.

Points #1 and #2 generally distinguish class variables from class-scoped type aliases in the vast majority of cases. Even if these heuristics fail and incorrectly identify a class variable as a type alias, it tends to work fine (no false positive errors). I don't recall ever receiving a bug report or a question about this, so it seems to work well.

I do agree that it would be beneficial to standardize this behavior across type checkers.

I know that some pyright users rely on our current behavior, so there could be some pain if we were to change it, but (depending on what we conclude here) there's likely a straightforward workaround we can offer the affected users.


Eric Traut
Contributor to Pyright & Pylance
Typing-sig mailing list --
To unsubscribe send an email to
Member address: